]> git.proxmox.com Git - rustc.git/commitdiff
Imported Upstream version 1.5.0+dfsg1
authorSylvestre Ledru <sylvestre@debian.org>
Thu, 10 Dec 2015 16:51:38 +0000 (17:51 +0100)
committerSylvestre Ledru <sylvestre@debian.org>
Thu, 10 Dec 2015 16:51:38 +0000 (17:51 +0100)
1058 files changed:
AUTHORS.txt
CONTRIBUTING.md
Makefile.in
README.md
RELEASES.md
configure
man/rustc.1
mk/cfg/mips-unknown-linux-gnu.mk
mk/cfg/mipsel-unknown-linux-gnu.mk
mk/cfg/x86_64-rumprun-netbsd.mk [new file with mode: 0644]
mk/cfg/x86_64-unknown-netbsd.mk
mk/crates.mk
mk/dist.mk
mk/grammar.mk
mk/install.mk
mk/llvm.mk
mk/main.mk
mk/platform.mk
mk/prepare.mk
mk/tests.mk
src/compiletest/compiletest.rs
src/compiletest/procsrv.rs
src/compiletest/runtest.rs
src/doc/README.md
src/doc/complement-lang-faq.md
src/doc/complement-project-faq.md
src/doc/grammar.md
src/doc/index.md
src/doc/nomicon/atomics.md
src/doc/nomicon/casts.md
src/doc/nomicon/concurrency.md
src/doc/nomicon/destructors.md
src/doc/nomicon/drop-flags.md
src/doc/nomicon/dropck.md
src/doc/nomicon/exotic-sizes.md
src/doc/nomicon/leaking.md
src/doc/nomicon/lifetime-mismatch.md
src/doc/nomicon/lifetimes.md
src/doc/nomicon/meet-safe-and-unsafe.md
src/doc/nomicon/other-reprs.md
src/doc/nomicon/ownership.md
src/doc/nomicon/races.md
src/doc/nomicon/repr-rust.md
src/doc/nomicon/safe-unsafe-meaning.md
src/doc/nomicon/send-and-sync.md
src/doc/nomicon/transmutes.md
src/doc/nomicon/unbounded-lifetimes.md
src/doc/nomicon/unchecked-uninit.md
src/doc/nomicon/uninitialized.md
src/doc/nomicon/unwinding.md
src/doc/nomicon/vec-layout.md
src/doc/nomicon/vec-push-pop.md
src/doc/nomicon/vec-zsts.md
src/doc/reference.md
src/doc/rust.css
src/doc/style/SUMMARY.md
src/doc/style/changing/README.md [deleted file]
src/doc/style/changing/post-1-0.md [deleted file]
src/doc/style/changing/pre-1-0.md [deleted file]
src/doc/style/changing/unclear.md [deleted file]
src/doc/style/errors/ergonomics.md
src/doc/style/features/modules.md
src/doc/style/features/traits/common.md
src/doc/style/features/traits/generics.md
src/doc/style/features/traits/reuse.md
src/doc/style/style/comments.md
src/doc/trpl/README.md
src/doc/trpl/SUMMARY.md
src/doc/trpl/advanced-linking.md
src/doc/trpl/bibliography.md
src/doc/trpl/casting-between-types.md
src/doc/trpl/choosing-your-guarantees.md
src/doc/trpl/closures.md
src/doc/trpl/compiler-plugins.md
src/doc/trpl/concurrency.md
src/doc/trpl/conditional-compilation.md
src/doc/trpl/crates-and-modules.md
src/doc/trpl/custom-allocators.md [new file with mode: 0644]
src/doc/trpl/dining-philosophers.md
src/doc/trpl/documentation.md
src/doc/trpl/error-handling.md
src/doc/trpl/getting-started.md
src/doc/trpl/glossary.md
src/doc/trpl/guessing-game.md
src/doc/trpl/hello-cargo.md
src/doc/trpl/hello-world.md
src/doc/trpl/if-let.md
src/doc/trpl/installing-rust.md
src/doc/trpl/iterators.md
src/doc/trpl/lifetimes.md
src/doc/trpl/method-syntax.md
src/doc/trpl/mutability.md
src/doc/trpl/no-stdlib.md
src/doc/trpl/ownership.md
src/doc/trpl/patterns.md
src/doc/trpl/primitive-types.md
src/doc/trpl/raw-pointers.md
src/doc/trpl/references-and-borrowing.md
src/doc/trpl/rust-inside-other-languages.md
src/doc/trpl/strings.md
src/doc/trpl/structs.md
src/doc/trpl/syntax-index.md [new file with mode: 0644]
src/doc/trpl/testing.md
src/doc/trpl/the-stack-and-the-heap.md
src/doc/trpl/traits.md
src/doc/trpl/variable-bindings.md
src/doc/trpl/vectors.md
src/driver/driver.rs
src/error-index-generator/main.rs
src/etc/generate-deriving-span-tests.py
src/etc/maketest.py
src/etc/mklldeps.py
src/etc/test-float-parse/runtests.py
src/etc/unicode.py
src/jemalloc/VERSION
src/liballoc/arc.rs
src/liballoc/boxed.rs
src/liballoc/boxed_test.rs
src/liballoc/heap.rs
src/liballoc/lib.rs
src/liballoc/raw_vec.rs
src/liballoc/rc.rs
src/liballoc_jemalloc/lib.rs
src/liballoc_system/lib.rs
src/libarena/lib.rs
src/libbacktrace/ChangeLog.jit
src/libbacktrace/Makefile.am
src/libbacktrace/Makefile.in
src/libbacktrace/alloc.c
src/libbacktrace/atomic.c
src/libbacktrace/backtrace-supported.h.in
src/libbacktrace/backtrace.c
src/libbacktrace/backtrace.h
src/libbacktrace/btest.c
src/libbacktrace/configure.ac
src/libbacktrace/dwarf.c
src/libbacktrace/dwarf2.def
src/libbacktrace/dwarf2.h
src/libbacktrace/elf.c
src/libbacktrace/fileline.c
src/libbacktrace/internal.h
src/libbacktrace/mmap.c
src/libbacktrace/mmapio.c
src/libbacktrace/nounwind.c
src/libbacktrace/posix.c
src/libbacktrace/print.c
src/libbacktrace/read.c
src/libbacktrace/simple.c
src/libbacktrace/sort.c
src/libbacktrace/state.c
src/libbacktrace/stest.c
src/libbacktrace/unknown.c
src/libcollections/binary_heap.rs
src/libcollections/btree/map.rs
src/libcollections/btree/node.rs
src/libcollections/btree/set.rs
src/libcollections/enum_set.rs
src/libcollections/fmt.rs
src/libcollections/lib.rs
src/libcollections/linked_list.rs
src/libcollections/slice.rs
src/libcollections/str.rs
src/libcollections/string.rs
src/libcollections/vec.rs
src/libcollections/vec_deque.rs
src/libcollectionstest/btree/map.rs
src/libcollectionstest/btree/set.rs
src/libcollectionstest/lib.rs
src/libcollectionstest/str.rs
src/libcollectionstest/string.rs
src/libcollectionstest/vec_deque.rs
src/libcore/array.rs
src/libcore/cell.rs
src/libcore/char.rs
src/libcore/cmp.rs
src/libcore/cmp_macros.rs
src/libcore/convert.rs
src/libcore/default.rs
src/libcore/fmt/builders.rs
src/libcore/fmt/mod.rs
src/libcore/fmt/num.rs
src/libcore/fmt/rt/v1.rs
src/libcore/hash/mod.rs
src/libcore/hash/sip.rs
src/libcore/intrinsics.rs
src/libcore/iter.rs
src/libcore/macros.rs
src/libcore/marker.rs
src/libcore/mem.rs
src/libcore/nonzero.rs
src/libcore/num/bignum.rs [new file with mode: 0644]
src/libcore/num/dec2flt/algorithm.rs
src/libcore/num/dec2flt/mod.rs
src/libcore/num/dec2flt/num.rs
src/libcore/num/dec2flt/rawfp.rs
src/libcore/num/diy_float.rs [new file with mode: 0644]
src/libcore/num/f32.rs
src/libcore/num/f64.rs
src/libcore/num/flt2dec/bignum.rs [deleted file]
src/libcore/num/flt2dec/mod.rs
src/libcore/num/flt2dec/strategy/dragon.rs
src/libcore/num/flt2dec/strategy/grisu.rs
src/libcore/num/mod.rs
src/libcore/ops.rs
src/libcore/option.rs
src/libcore/ptr.rs
src/libcore/raw.rs
src/libcore/result.rs
src/libcore/slice.rs
src/libcore/str/mod.rs
src/libcore/sync/atomic.rs
src/libcoretest/cell.rs
src/libcoretest/clone.rs
src/libcoretest/fmt/float.rs
src/libcoretest/fmt/mod.rs
src/libcoretest/intrinsics.rs
src/libcoretest/lib.rs
src/libcoretest/num/bignum.rs [new file with mode: 0644]
src/libcoretest/num/dec2flt/mod.rs
src/libcoretest/num/dec2flt/rawfp.rs
src/libcoretest/num/flt2dec/bignum.rs [deleted file]
src/libcoretest/num/flt2dec/mod.rs
src/libcoretest/num/flt2dec/strategy/dragon.rs
src/libcoretest/num/mod.rs
src/libflate/lib.rs
src/libfmt_macros/lib.rs
src/libgraphviz/lib.rs
src/liblibc/lib.rs
src/liblog/directive.rs
src/liblog/lib.rs
src/librand/chacha.rs
src/librand/distributions/exponential.rs
src/librand/distributions/gamma.rs
src/librand/distributions/mod.rs
src/librand/distributions/normal.rs
src/librand/distributions/range.rs
src/librand/distributions/ziggurat_tables.rs
src/librand/isaac.rs
src/librand/lib.rs
src/librand/rand_impls.rs
src/librand/reseeding.rs
src/librbml/lib.rs
src/librustc/diagnostics.rs
src/librustc/front/check_attr.rs [new file with mode: 0644]
src/librustc/front/map/blocks.rs
src/librustc/front/map/collector.rs [new file with mode: 0644]
src/librustc/front/map/definitions.rs [new file with mode: 0644]
src/librustc/front/map/mod.rs
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/lint/context.rs
src/librustc/lint/mod.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/index.rs
src/librustc/metadata/loader.rs
src/librustc/metadata/macro_import.rs
src/librustc/metadata/tydecode.rs
src/librustc/metadata/tyencode.rs
src/librustc/middle/astconv_util.rs
src/librustc/middle/astencode.rs
src/librustc/middle/cfg/construct.rs
src/librustc/middle/check_const.rs
src/librustc/middle/check_match.rs
src/librustc/middle/check_no_asm.rs
src/librustc/middle/check_static_recursion.rs
src/librustc/middle/const_eval.rs
src/librustc/middle/dataflow.rs
src/librustc/middle/dead.rs
src/librustc/middle/def.rs
src/librustc/middle/def_id.rs
src/librustc/middle/effect.rs
src/librustc/middle/entry.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/free_region.rs
src/librustc/middle/infer/combine.rs
src/librustc/middle/infer/equate.rs
src/librustc/middle/infer/error_reporting.rs
src/librustc/middle/infer/higher_ranked/mod.rs
src/librustc/middle/infer/mod.rs
src/librustc/middle/infer/region_inference/README.md
src/librustc/middle/infer/region_inference/mod.rs
src/librustc/middle/infer/sub.rs
src/librustc/middle/infer/unify_key.rs
src/librustc/middle/intrinsicck.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/pat_util.rs
src/librustc/middle/reachable.rs
src/librustc/middle/region.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/stability.rs
src/librustc/middle/traits/coherence.rs
src/librustc/middle/traits/error_reporting.rs
src/librustc/middle/traits/mod.rs
src/librustc/middle/traits/object_safety.rs
src/librustc/middle/traits/select.rs
src/librustc/middle/traits/util.rs
src/librustc/middle/ty/adjustment.rs
src/librustc/middle/ty/cast.rs
src/librustc/middle/ty/contents.rs
src/librustc/middle/ty/context.rs
src/librustc/middle/ty/error.rs
src/librustc/middle/ty/fast_reject.rs
src/librustc/middle/ty/mod.rs
src/librustc/middle/ty/structural_impls.rs
src/librustc/middle/ty/sty.rs
src/librustc/middle/ty/util.rs
src/librustc/middle/weak_lang_items.rs
src/librustc/plugin/build.rs
src/librustc/plugin/load.rs
src/librustc/plugin/registry.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/util/ppaux.rs
src/librustc_back/lib.rs
src/librustc_back/slice.rs [new file with mode: 0644]
src/librustc_back/svh.rs
src/librustc_back/target/aarch64_apple_ios.rs
src/librustc_back/target/aarch64_linux_android.rs
src/librustc_back/target/aarch64_unknown_linux_gnu.rs
src/librustc_back/target/apple_base.rs
src/librustc_back/target/arm_linux_androideabi.rs
src/librustc_back/target/arm_unknown_linux_gnueabi.rs
src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
src/librustc_back/target/armv7_apple_ios.rs
src/librustc_back/target/armv7s_apple_ios.rs
src/librustc_back/target/bitrig_base.rs
src/librustc_back/target/dragonfly_base.rs
src/librustc_back/target/freebsd_base.rs
src/librustc_back/target/i386_apple_ios.rs
src/librustc_back/target/i686_apple_darwin.rs
src/librustc_back/target/i686_linux_android.rs
src/librustc_back/target/i686_pc_windows_gnu.rs
src/librustc_back/target/i686_pc_windows_msvc.rs
src/librustc_back/target/i686_unknown_dragonfly.rs
src/librustc_back/target/i686_unknown_freebsd.rs
src/librustc_back/target/i686_unknown_linux_gnu.rs
src/librustc_back/target/le32_unknown_nacl.rs [new file with mode: 0644]
src/librustc_back/target/linux_base.rs
src/librustc_back/target/mips_unknown_linux_gnu.rs
src/librustc_back/target/mipsel_unknown_linux_gnu.rs
src/librustc_back/target/mod.rs
src/librustc_back/target/openbsd_base.rs
src/librustc_back/target/powerpc_unknown_linux_gnu.rs
src/librustc_back/target/windows_base.rs
src/librustc_back/target/windows_msvc_base.rs
src/librustc_back/target/x86_64_apple_darwin.rs
src/librustc_back/target/x86_64_apple_ios.rs
src/librustc_back/target/x86_64_pc_windows_gnu.rs
src/librustc_back/target/x86_64_pc_windows_msvc.rs
src/librustc_back/target/x86_64_rumprun_netbsd.rs [new file with mode: 0644]
src/librustc_back/target/x86_64_unknown_bitrig.rs
src/librustc_back/target/x86_64_unknown_dragonfly.rs
src/librustc_back/target/x86_64_unknown_freebsd.rs
src/librustc_back/target/x86_64_unknown_linux_gnu.rs
src/librustc_back/target/x86_64_unknown_linux_musl.rs
src/librustc_back/target/x86_64_unknown_netbsd.rs
src/librustc_back/target/x86_64_unknown_openbsd.rs
src/librustc_bitflags/lib.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/fragments.rs
src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
src/librustc_borrowck/borrowck/gather_loans/move_error.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/diagnostics.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_driver/test.rs
src/librustc_front/attr.rs [deleted file]
src/librustc_front/fold.rs
src/librustc_front/hir.rs
src/librustc_front/lib.rs
src/librustc_front/lowering.rs
src/librustc_front/print/pp.rs [deleted file]
src/librustc_front/print/pprust.rs
src/librustc_front/util.rs
src/librustc_front/visit.rs
src/librustc_lint/bad_style.rs [new file with mode: 0644]
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_lint/types.rs [new file with mode: 0644]
src/librustc_lint/unused.rs [new file with mode: 0644]
src/librustc_llvm/lib.rs
src/librustc_mir/build/block.rs
src/librustc_mir/build/cfg.rs
src/librustc_mir/build/expr/as_constant.rs
src/librustc_mir/build/expr/as_lvalue.rs
src/librustc_mir/build/expr/as_operand.rs
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/build/expr/as_temp.rs
src/librustc_mir/build/expr/category.rs
src/librustc_mir/build/expr/into.rs
src/librustc_mir/build/into.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/matches/simplify.rs
src/librustc_mir/build/matches/test.rs
src/librustc_mir/build/matches/util.rs
src/librustc_mir/build/misc.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/build/scope.rs
src/librustc_mir/build/stmt.rs
src/librustc_mir/dump.rs [deleted file]
src/librustc_mir/graphviz/mod.rs
src/librustc_mir/hair.rs
src/librustc_mir/lib.rs
src/librustc_mir/mir_map.rs [new file with mode: 0644]
src/librustc_mir/repr.rs
src/librustc_mir/tcx/block.rs
src/librustc_mir/tcx/expr.rs
src/librustc_mir/tcx/mod.rs
src/librustc_mir/tcx/pattern.rs
src/librustc_mir/tcx/to_ref.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/diagnostics.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/record_exports.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_trans/back/archive.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/linker.rs
src/librustc_trans/back/lto.rs
src/librustc_trans/back/write.rs
src/librustc_trans/diagnostics.rs [new file with mode: 0644]
src/librustc_trans/lib.rs
src/librustc_trans/save/dump_csv.rs
src/librustc_trans/save/mod.rs
src/librustc_trans/save/recorder.rs
src/librustc_trans/save/span_utils.rs
src/librustc_trans/trans/_match.rs
src/librustc_trans/trans/adt.rs
src/librustc_trans/trans/asm.rs
src/librustc_trans/trans/attributes.rs
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/cabi_x86_64.rs
src/librustc_trans/trans/cabi_x86_win64.rs
src/librustc_trans/trans/callee.rs
src/librustc_trans/trans/closure.rs
src/librustc_trans/trans/common.rs
src/librustc_trans/trans/consts.rs
src/librustc_trans/trans/context.rs
src/librustc_trans/trans/controlflow.rs
src/librustc_trans/trans/debuginfo/create_scope_map.rs
src/librustc_trans/trans/debuginfo/gdb.rs
src/librustc_trans/trans/debuginfo/metadata.rs
src/librustc_trans/trans/debuginfo/mod.rs
src/librustc_trans/trans/debuginfo/type_names.rs
src/librustc_trans/trans/debuginfo/utils.rs
src/librustc_trans/trans/expr.rs
src/librustc_trans/trans/foreign.rs
src/librustc_trans/trans/glue.rs
src/librustc_trans/trans/inline.rs
src/librustc_trans/trans/intrinsic.rs
src/librustc_trans/trans/meth.rs
src/librustc_trans/trans/monomorphize.rs
src/librustc_trans/trans/tvec.rs
src/librustc_trans/trans/type_.rs
src/librustc_trans/trans/type_of.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/op.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/upvar.rs
src/librustc_typeck/check/wf.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/orphan.rs
src/librustc_typeck/coherence/overlap.rs
src/librustc_typeck/coherence/unsafety.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustc_typeck/variance.rs
src/librustc_unicode/char.rs
src/librustc_unicode/lib.rs
src/librustc_unicode/u_str.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs
src/librustdoc/doctree.rs
src/librustdoc/html/format.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/COPYRIGHT.txt [new file with mode: 0644]
src/librustdoc/html/static/LICENSE-APACHE.txt [new file with mode: 0644]
src/librustdoc/html/static/LICENSE-MIT.txt [new file with mode: 0644]
src/librustdoc/html/static/main.css
src/librustdoc/html/static/main.js
src/librustdoc/html/static/playpen.js
src/librustdoc/html/toc.rs
src/librustdoc/lib.rs
src/librustdoc/passes.rs
src/librustdoc/plugins.rs
src/librustdoc/test.rs
src/librustdoc/visit_ast.rs
src/libserialize/json.rs
src/libstd/collections/hash/map.rs
src/libstd/collections/hash/set.rs
src/libstd/collections/hash/table.rs
src/libstd/collections/mod.rs
src/libstd/dynamic_lib.rs
src/libstd/env.rs
src/libstd/ffi/c_str.rs
src/libstd/ffi/mod.rs
src/libstd/fs.rs
src/libstd/io/buffered.rs
src/libstd/io/cursor.rs
src/libstd/io/error.rs
src/libstd/io/impls.rs
src/libstd/io/mod.rs
src/libstd/io/prelude.rs
src/libstd/io/stdio.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/net/ip.rs
src/libstd/net/parser.rs
src/libstd/net/tcp.rs
src/libstd/net/test.rs
src/libstd/net/udp.rs
src/libstd/os/android/raw.rs
src/libstd/os/bitrig/raw.rs
src/libstd/os/dragonfly/raw.rs
src/libstd/os/freebsd/raw.rs
src/libstd/os/ios/raw.rs
src/libstd/os/linux/raw.rs
src/libstd/os/macos/raw.rs
src/libstd/os/nacl/raw.rs
src/libstd/os/netbsd/raw.rs
src/libstd/os/openbsd/raw.rs
src/libstd/panicking.rs
src/libstd/path.rs
src/libstd/prelude/mod.rs
src/libstd/primitive_docs.rs
src/libstd/process.rs
src/libstd/sync/condvar.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sync/mutex.rs
src/libstd/sync/rwlock.rs
src/libstd/sys/common/libunwind.rs
src/libstd/sys/common/unwind/mod.rs
src/libstd/sys/common/wtf8.rs
src/libstd/sys/unix/c.rs
src/libstd/sys/unix/ext/fs.rs
src/libstd/sys/unix/ext/process.rs
src/libstd/sys/unix/fs.rs
src/libstd/sys/unix/mod.rs
src/libstd/sys/unix/os.rs
src/libstd/sys/unix/process.rs
src/libstd/sys/unix/stack_overflow.rs
src/libstd/sys/unix/sync.rs
src/libstd/sys/unix/thread.rs
src/libstd/sys/unix/time.rs
src/libstd/sys/windows/backtrace.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/fs.rs
src/libstd/sys/windows/mod.rs
src/libstd/sys/windows/mutex.rs
src/libstd/sys/windows/printing/gnu.rs
src/libstd/sys/windows/printing/msvc.rs
src/libstd/thread/mod.rs
src/libstd/time/duration.rs
src/libsyntax/ast.rs
src/libsyntax/ast_util.rs
src/libsyntax/attr.rs
src/libsyntax/codemap.rs
src/libsyntax/config.rs
src/libsyntax/diagnostic.rs
src/libsyntax/diagnostics/plugin.rs
src/libsyntax/entry.rs
src/libsyntax/ext/asm.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/deriving/debug.rs [new file with mode: 0644]
src/libsyntax/ext/deriving/generic/mod.rs
src/libsyntax/ext/deriving/mod.rs
src/libsyntax/ext/deriving/primitive.rs
src/libsyntax/ext/deriving/show.rs [deleted file]
src/libsyntax/ext/expand.rs
src/libsyntax/ext/mtwt.rs
src/libsyntax/ext/pushpop_safe.rs [deleted file]
src/libsyntax/ext/quote.rs
src/libsyntax/ext/tt/macro_parser.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/ext/tt/transcribe.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/lib.rs
src/libsyntax/owned_slice.rs
src/libsyntax/parse/attr.rs
src/libsyntax/parse/lexer/comments.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/libsyntax/std_inject.rs
src/libsyntax/util/interner.rs
src/libsyntax/util/small_vector.rs
src/libsyntax/visit.rs
src/libterm/lib.rs
src/libterm/terminfo/searcher.rs
src/libtest/lib.rs
src/rt/hoedown/bin/hoedown.c
src/rt/hoedown/src/document.c
src/rt/hoedown/src/version.h
src/rt/rust_test_helpers.c
src/rustbook/build.rs
src/rustbook/help.rs
src/rustbook/javascript.rs [deleted file]
src/rustbook/main.rs
src/rustbook/static/rustbook.css
src/rustbook/static/rustbook.js
src/rustbook/subcommand.rs
src/rustllvm/ArchiveWrapper.cpp
src/rustllvm/PassWrapper.cpp
src/rustllvm/RustWrapper.cpp
src/rustllvm/llvm-auto-clean-trigger
src/test/auxiliary/augmented_assignments.rs [new file with mode: 0644]
src/test/auxiliary/cross_crate_spans.rs
src/test/auxiliary/inherited_stability.rs
src/test/auxiliary/issue-2380.rs
src/test/auxiliary/issue-29181.rs [new file with mode: 0644]
src/test/auxiliary/lint_for_crate.rs
src/test/auxiliary/lint_group_plugin_test.rs
src/test/auxiliary/lint_output_format.rs
src/test/auxiliary/lint_plugin_test.rs
src/test/auxiliary/lint_stability.rs
src/test/auxiliary/lint_stability_fields.rs
src/test/auxiliary/procedural_mbe_matching.rs
src/test/auxiliary/sepcomp_cci_lib.rs
src/test/auxiliary/xcrate_static_addresses.rs
src/test/bench/core-map.rs
src/test/bench/shootout-fasta-redux.rs
src/test/bench/shootout-fasta.rs
src/test/bench/shootout-mandelbrot.rs
src/test/bench/shootout-nbody.rs
src/test/borrowck-loan-of-static-data-issue-27616.rs [deleted file]
src/test/codegen/adjustments.rs [new file with mode: 0644]
src/test/codegen/coercions.rs
src/test/codegen/consts.rs [new file with mode: 0644]
src/test/codegen/extern-functions.rs
src/test/codegen/function-arguments.rs
src/test/codegen/gdb_debug_script_load.rs [new file with mode: 0644]
src/test/codegen/link_section.rs
src/test/codegen/loads.rs
src/test/codegen/match.rs [new file with mode: 0644]
src/test/codegen/refs.rs [new file with mode: 0644]
src/test/codegen/stores.rs
src/test/compile-fail/assignment-operator-unimplemented.rs
src/test/compile-fail/associated-types-invalid-trait-ref-issue-18865.rs
src/test/compile-fail/attr-usage-inline.rs [new file with mode: 0644]
src/test/compile-fail/attr-usage-repr.rs [new file with mode: 0644]
src/test/compile-fail/augmented-assignments-feature-gate-cross.rs [new file with mode: 0644]
src/test/compile-fail/augmented-assignments-feature-gate.rs [new file with mode: 0644]
src/test/compile-fail/augmented-assignments-trait.rs [new file with mode: 0644]
src/test/compile-fail/augmented-assignments.rs [new file with mode: 0644]
src/test/compile-fail/autoderef-full-lval.rs
src/test/compile-fail/borrow-tuple-fields.rs
src/test/compile-fail/borrowck-argument.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs
src/test/compile-fail/borrowck-closures-unique.rs
src/test/compile-fail/borrowck-lend-flow-if.rs
src/test/compile-fail/borrowck-lend-flow-loop.rs
src/test/compile-fail/borrowck-lend-flow.rs
src/test/compile-fail/borrowck-loan-in-overloaded-op.rs
src/test/compile-fail/borrowck-loan-of-static-data-issue-27616.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-mut-borrow-linear-errors.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-unboxed-closures.rs
src/test/compile-fail/cast-as-bool.rs
src/test/compile-fail/const-err.rs [new file with mode: 0644]
src/test/compile-fail/const-eval-overflow.rs
src/test/compile-fail/const-eval-span.rs [new file with mode: 0644]
src/test/compile-fail/const-fn-destructuring-arg.rs [new file with mode: 0644]
src/test/compile-fail/const-fn-stability-calls-2.rs
src/test/compile-fail/const-len-underflow-separate-spans.rs
src/test/compile-fail/const-len-underflow-subspans.rs
src/test/compile-fail/const-slice-oob.rs [new file with mode: 0644]
src/test/compile-fail/deriving-primitive.rs
src/test/compile-fail/dropck_arr_cycle_checked.rs
src/test/compile-fail/dropck_tarena_cycle_checked.rs
src/test/compile-fail/dropck_tarena_unsound_drop.rs
src/test/compile-fail/dropck_trait_cycle_checked.rs
src/test/compile-fail/dropck_vec_cycle_checked.rs
src/test/compile-fail/dupe-symbols-8.rs [new file with mode: 0644]
src/test/compile-fail/empty-comment.rs [new file with mode: 0644]
src/test/compile-fail/empty-struct-braces-expr.rs [new file with mode: 0644]
src/test/compile-fail/empty-struct-braces-gate-1.rs [new file with mode: 0644]
src/test/compile-fail/empty-struct-braces-gate-2.rs [new file with mode: 0644]
src/test/compile-fail/empty-struct-braces-pat-1.rs [new file with mode: 0644]
src/test/compile-fail/empty-struct-braces-pat-2.rs [new file with mode: 0644]
src/test/compile-fail/empty-struct-unit-expr.rs [new file with mode: 0644]
src/test/compile-fail/empty-struct-unit-pat.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate-box-expr.rs
src/test/compile-fail/feature-gate-cfg-target-vendor.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate-dropck-ugeh.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate-negate-unsigned.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate-no-debug.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate-omit-gdb-pretty-printer-section.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate-placement-expr.rs
src/test/compile-fail/feature-gate-pushpop-unsafe.rs [deleted file]
src/test/compile-fail/feature-gated-feature-in-macro-arg.rs
src/test/compile-fail/for-expn-2.rs [deleted file]
src/test/compile-fail/for-loop-hygiene.rs
src/test/compile-fail/for-loop-refutable-pattern-error-message.rs
src/test/compile-fail/invalid-path-in-const.rs [new file with mode: 0644]
src/test/compile-fail/issue-14084.rs
src/test/compile-fail/issue-15167.rs
src/test/compile-fail/issue-15381.rs
src/test/compile-fail/issue-16819.rs [new file with mode: 0644]
src/test/compile-fail/issue-17283.rs
src/test/compile-fail/issue-17337.rs
src/test/compile-fail/issue-17904-2.rs
src/test/compile-fail/issue-18959.rs
src/test/compile-fail/issue-1920-2.rs
src/test/compile-fail/issue-21546.rs [new file with mode: 0644]
src/test/compile-fail/issue-22599.rs [new file with mode: 0644]
src/test/compile-fail/issue-22872.rs [deleted file]
src/test/compile-fail/issue-23046.rs
src/test/compile-fail/issue-23543.rs [new file with mode: 0644]
src/test/compile-fail/issue-23544.rs [new file with mode: 0644]
src/test/compile-fail/issue-23729.rs
src/test/compile-fail/issue-25145.rs [new file with mode: 0644]
src/test/compile-fail/issue-26056.rs [new file with mode: 0644]
src/test/compile-fail/issue-26459.rs [new file with mode: 0644]
src/test/compile-fail/issue-26886.rs [new file with mode: 0644]
src/test/compile-fail/issue-26905.rs [new file with mode: 0644]
src/test/compile-fail/issue-27831.rs
src/test/compile-fail/issue-27895.rs [new file with mode: 0644]
src/test/compile-fail/issue-28075.rs [new file with mode: 0644]
src/test/compile-fail/issue-28388-1.rs [new file with mode: 0644]
src/test/compile-fail/issue-28388-2.rs [new file with mode: 0644]
src/test/compile-fail/issue-28388-3.rs [new file with mode: 0644]
src/test/compile-fail/issue-28433.rs [new file with mode: 0644]
src/test/compile-fail/issue-28472.rs [new file with mode: 0644]
src/test/compile-fail/issue-28576.rs [new file with mode: 0644]
src/test/compile-fail/issue-28776.rs [new file with mode: 0644]
src/test/compile-fail/issue-28837.rs [new file with mode: 0644]
src/test/compile-fail/issue-29106.rs [new file with mode: 0644]
src/test/compile-fail/issue-29161.rs [new file with mode: 0644]
src/test/compile-fail/issue-29181.rs [new file with mode: 0644]
src/test/compile-fail/issue-29184.rs [new file with mode: 0644]
src/test/compile-fail/issue-3993-2.rs [deleted file]
src/test/compile-fail/issue-6801.rs
src/test/compile-fail/issue-8460-const.rs
src/test/compile-fail/issue28498-reject-ex1.rs [new file with mode: 0644]
src/test/compile-fail/issue28498-reject-lifetime-param.rs [new file with mode: 0644]
src/test/compile-fail/issue28498-reject-passed-to-fn.rs [new file with mode: 0644]
src/test/compile-fail/issue28498-reject-trait-bound.rs [new file with mode: 0644]
src/test/compile-fail/lint-output-format.rs
src/test/compile-fail/lint-stability-fields.rs
src/test/compile-fail/lint-stability.rs
src/test/compile-fail/lint-visible-private-types.rs
src/test/compile-fail/loop-does-not-diverge.rs
src/test/compile-fail/moves-based-on-type-tuple.rs
src/test/compile-fail/object-safety-issue-22040.rs
src/test/compile-fail/object-safety-supertrait-mentions-Self.rs
src/test/compile-fail/packed-struct-generic-transmute.rs
src/test/compile-fail/packed-struct-transmute.rs
src/test/compile-fail/placement-expr-unsafe.rs [new file with mode: 0644]
src/test/compile-fail/placement-expr-unstable.rs [new file with mode: 0644]
src/test/compile-fail/privacy-ufcs.rs [new file with mode: 0644]
src/test/compile-fail/pushpop-unsafe-rejects.rs [deleted file]
src/test/compile-fail/regions-outlives-projection-container-hrtb.rs
src/test/compile-fail/stability-attribute-sanity-2.rs [new file with mode: 0644]
src/test/compile-fail/stability-attribute-sanity.rs
src/test/compile-fail/struct-no-fields-enumlike.rs [new file with mode: 0644]
src/test/compile-fail/trait-not-accessible.rs [new file with mode: 0644]
src/test/compile-fail/trait-test-2.rs
src/test/compile-fail/transmute-different-sizes.rs
src/test/compile-fail/transmute-fat-pointers.rs
src/test/compile-fail/transmute-impl.rs
src/test/compile-fail/transmute-imut-to-mut.rs
src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs
src/test/compile-fail/unsafe-const-fn.rs [new file with mode: 0644]
src/test/compile-fail/useless-priv.rs [deleted file]
src/test/compile-fail/useless-pub.rs [new file with mode: 0644]
src/test/compile-fail/variance-regions-direct.rs
src/test/compile-fail/variance-trait-bounds.rs
src/test/compile-fail/variance-types.rs
src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs
src/test/compile-fail/wf-method-late-bound-regions.rs [new file with mode: 0644]
src/test/compile-fail/wf-misc-methods-issue-28609.rs [new file with mode: 0644]
src/test/compile-fail/wf-static-method.rs [new file with mode: 0644]
src/test/debuginfo/associated-types.rs
src/test/debuginfo/basic-types-globals-metadata.rs
src/test/debuginfo/basic-types-globals.rs
src/test/debuginfo/basic-types-metadata.rs
src/test/debuginfo/basic-types-mut-globals.rs
src/test/debuginfo/basic-types.rs
src/test/debuginfo/borrowed-basic.rs
src/test/debuginfo/borrowed-c-style-enum.rs
src/test/debuginfo/borrowed-enum.rs
src/test/debuginfo/borrowed-struct.rs
src/test/debuginfo/borrowed-tuple.rs
src/test/debuginfo/borrowed-unique-basic.rs
src/test/debuginfo/box.rs
src/test/debuginfo/boxed-struct.rs
src/test/debuginfo/by-value-non-immediate-argument.rs
src/test/debuginfo/by-value-self-argument-in-trait-impl.rs
src/test/debuginfo/c-style-enum-in-composite.rs
src/test/debuginfo/c-style-enum.rs
src/test/debuginfo/closure-in-generic-function.rs
src/test/debuginfo/constant-debug-locs.rs
src/test/debuginfo/constant-in-match-pattern.rs
src/test/debuginfo/cross-crate-spans.rs
src/test/debuginfo/destructured-fn-argument.rs
src/test/debuginfo/destructured-for-loop-variable.rs
src/test/debuginfo/destructured-local.rs
src/test/debuginfo/evec-in-struct.rs
src/test/debuginfo/extern-c-fn.rs
src/test/debuginfo/function-arg-initialization.rs
src/test/debuginfo/function-arguments.rs
src/test/debuginfo/function-prologue-stepping-no-stack-check.rs
src/test/debuginfo/function-prologue-stepping-regular.rs
src/test/debuginfo/generic-enum-with-different-disr-sizes.rs
src/test/debuginfo/generic-function.rs
src/test/debuginfo/generic-functions-nested.rs
src/test/debuginfo/generic-method-on-generic-struct.rs
src/test/debuginfo/generic-static-method-on-struct-and-enum.rs
src/test/debuginfo/generic-struct-style-enum.rs
src/test/debuginfo/generic-struct.rs
src/test/debuginfo/generic-tuple-style-enum.rs
src/test/debuginfo/include_string.rs
src/test/debuginfo/issue12886.rs
src/test/debuginfo/issue22656.rs
src/test/debuginfo/lexical-scope-in-for-loop.rs
src/test/debuginfo/lexical-scope-in-if.rs
src/test/debuginfo/lexical-scope-in-match.rs
src/test/debuginfo/lexical-scope-in-stack-closure.rs
src/test/debuginfo/lexical-scope-in-unconditional-loop.rs
src/test/debuginfo/lexical-scope-in-unique-closure.rs
src/test/debuginfo/lexical-scope-in-while.rs
src/test/debuginfo/lexical-scope-with-macro.rs
src/test/debuginfo/lexical-scopes-in-block-expression.rs
src/test/debuginfo/limited-debuginfo.rs
src/test/debuginfo/method-on-enum.rs
src/test/debuginfo/method-on-generic-struct.rs
src/test/debuginfo/method-on-struct.rs
src/test/debuginfo/method-on-trait.rs
src/test/debuginfo/method-on-tuple-struct.rs
src/test/debuginfo/multiple-functions-equal-var-names.rs
src/test/debuginfo/multiple-functions.rs
src/test/debuginfo/name-shadowing-and-scope-nesting.rs
src/test/debuginfo/nil-enum.rs
src/test/debuginfo/no-debug-attribute.rs
src/test/debuginfo/option-like-enum.rs
src/test/debuginfo/packed-struct-with-destructor.rs
src/test/debuginfo/packed-struct.rs
src/test/debuginfo/recursive-enum.rs
src/test/debuginfo/recursive-struct.rs
src/test/debuginfo/self-in-default-method.rs
src/test/debuginfo/self-in-generic-default-method.rs
src/test/debuginfo/shadowed-argument.rs
src/test/debuginfo/shadowed-variable.rs
src/test/debuginfo/simd.rs
src/test/debuginfo/simple-lexical-scope.rs
src/test/debuginfo/simple-struct.rs
src/test/debuginfo/simple-tuple.rs
src/test/debuginfo/static-method-on-struct-and-enum.rs
src/test/debuginfo/struct-in-enum.rs
src/test/debuginfo/struct-in-struct.rs
src/test/debuginfo/struct-style-enum.rs
src/test/debuginfo/struct-with-destructor.rs
src/test/debuginfo/trait-pointers.rs
src/test/debuginfo/tuple-in-struct.rs
src/test/debuginfo/tuple-in-tuple.rs
src/test/debuginfo/tuple-struct.rs
src/test/debuginfo/tuple-style-enum.rs
src/test/debuginfo/type-names.rs
src/test/debuginfo/unique-enum.rs
src/test/debuginfo/unreachable-locals.rs
src/test/debuginfo/var-captured-in-nested-closure.rs
src/test/debuginfo/var-captured-in-sendable-closure.rs
src/test/debuginfo/var-captured-in-stack-closure.rs
src/test/debuginfo/vec-slices.rs
src/test/debuginfo/vec.rs
src/test/parse-fail/lifetime-in-pattern.rs [new file with mode: 0644]
src/test/parse-fail/parenthesized-box-expr-message.rs [deleted file]
src/test/parse-fail/struct-no-fields-2.rs [deleted file]
src/test/parse-fail/struct-no-fields-3.rs [deleted file]
src/test/parse-fail/struct-no-fields-4.rs [deleted file]
src/test/parse-fail/struct-no-fields-5.rs [deleted file]
src/test/parse-fail/struct-no-fields-enumlike.rs [deleted file]
src/test/parse-fail/struct-no-fields.rs [deleted file]
src/test/parse-fail/struct-variant-no-fields.rs [deleted file]
src/test/pretty/issue-4264.pp
src/test/run-fail/issue-18576.rs
src/test/run-fail/issue-28934.rs [new file with mode: 0644]
src/test/run-fail/overflowing-add.rs
src/test/run-fail/overflowing-lsh-1.rs
src/test/run-fail/overflowing-lsh-2.rs
src/test/run-fail/overflowing-lsh-3.rs
src/test/run-fail/overflowing-lsh-4.rs
src/test/run-fail/overflowing-mul.rs
src/test/run-fail/overflowing-neg.rs
src/test/run-fail/overflowing-rsh-1.rs
src/test/run-fail/overflowing-rsh-2.rs
src/test/run-fail/overflowing-rsh-3.rs
src/test/run-fail/overflowing-rsh-4.rs
src/test/run-fail/overflowing-sub.rs
src/test/run-make/allow-non-lint-warnings-cmdline/1 [deleted file]
src/test/run-make/allow-warnings-cmdline-stability/1 [deleted file]
src/test/run-make/archive-duplicate-names/Makefile
src/test/run-make/bare-outfile/Makefile
src/test/run-make/c-dynamic-dylib/cfoo.c
src/test/run-make/c-dynamic-rlib/cfoo.c
src/test/run-make/c-link-to-rust-dylib/Makefile
src/test/run-make/c-link-to-rust-staticlib/Makefile
src/test/run-make/c-static-dylib/Makefile
src/test/run-make/c-static-rlib/Makefile
src/test/run-make/compile-stdin/Makefile [new file with mode: 0644]
src/test/run-make/crate-name-priority/Makefile
src/test/run-make/dep-info/Makefile
src/test/run-make/dep-info/lib2.rs [new file with mode: 0644]
src/test/run-make/execution-engine/test.rs
src/test/run-make/extern-fn-generic/Makefile
src/test/run-make/extern-fn-mangle/Makefile
src/test/run-make/extern-fn-struct-passing-abi/Makefile [new file with mode: 0644]
src/test/run-make/extern-fn-struct-passing-abi/test.c [new file with mode: 0644]
src/test/run-make/extern-fn-struct-passing-abi/test.rs [new file with mode: 0644]
src/test/run-make/extern-fn-with-packed-struct/Makefile
src/test/run-make/extern-fn-with-packed-struct/test.c
src/test/run-make/extern-fn-with-union/Makefile
src/test/run-make/interdependent-c-libraries/Makefile
src/test/run-make/invalid-staticlib/Makefile [new file with mode: 0644]
src/test/run-make/issue-12446/Makefile [deleted file]
src/test/run-make/issue-12446/bar.rs [deleted file]
src/test/run-make/issue-12446/foo.c [deleted file]
src/test/run-make/issue-12446/foo.rs [deleted file]
src/test/run-make/issue-14500/Makefile
src/test/run-make/issue-14698/Makefile [new file with mode: 0644]
src/test/run-make/issue-14698/foo.rs [new file with mode: 0644]
src/test/run-make/issue-15460/Makefile
src/test/run-make/issue-15460/foo.c
src/test/run-make/issue-15460/foo.rs
src/test/run-make/issue-19371/foo.rs
src/test/run-make/issue-25581/Makefile
src/test/run-make/issue-26092/Makefile
src/test/run-make/issue-28595/Makefile [new file with mode: 0644]
src/test/run-make/issue-28595/a.c [new file with mode: 0644]
src/test/run-make/issue-28595/a.rs [new file with mode: 0644]
src/test/run-make/issue-28595/b.c [new file with mode: 0644]
src/test/run-make/issue-28595/b.rs [new file with mode: 0644]
src/test/run-make/link-path-order/Makefile
src/test/run-make/linkage-attr-on-static/Makefile
src/test/run-make/linkage-attr-on-static/bar.rs
src/test/run-make/linker-output-non-utf8/Makefile [new file with mode: 0644]
src/test/run-make/linker-output-non-utf8/exec.rs [new file with mode: 0644]
src/test/run-make/linker-output-non-utf8/library.rs [new file with mode: 0644]
src/test/run-make/lto-smoke-c/Makefile
src/test/run-make/no-duplicate-libs/Makefile
src/test/run-make/no-duplicate-libs/bar.c [deleted file]
src/test/run-make/no-duplicate-libs/foo.c [deleted file]
src/test/run-make/output-type-permutations/Makefile
src/test/run-make/relocation-model/Makefile
src/test/run-make/save-analysis/Makefile
src/test/run-make/save-analysis/foo.rs
src/test/run-make/static-dylib-by-default/Makefile
src/test/run-make/tools.mk
src/test/run-pass-fulldeps/rename-directory.rs
src/test/run-pass/arr_cycle.rs
src/test/run-pass/augmented-assignments.rs [new file with mode: 0644]
src/test/run-pass/autoderef-method-on-trait.rs
src/test/run-pass/borrowck-rvalues-mutable.rs
src/test/run-pass/cfg-target-vendor.rs [new file with mode: 0644]
src/test/run-pass/const-adt-align-mismatch.rs
src/test/run-pass/const-fn-const-eval.rs [new file with mode: 0644]
src/test/run-pass/const-unsafe-fn.rs [new file with mode: 0644]
src/test/run-pass/core-run-destroy.rs
src/test/run-pass/crate-method-reexport-grrrrrrr.rs
src/test/run-pass/deprecated-derive.rs
src/test/run-pass/dropck_legal_cycles.rs
src/test/run-pass/dropck_tarena_sound_drop.rs
src/test/run-pass/empty-struct-braces.rs [new file with mode: 0644]
src/test/run-pass/feature-gate-negate-unsigned.rs [deleted file]
src/test/run-pass/ifmt.rs
src/test/run-pass/impl-inherent-non-conflict.rs
src/test/run-pass/issue-10767.rs
src/test/run-pass/issue-11047.rs [new file with mode: 0644]
src/test/run-pass/issue-11577.rs
src/test/run-pass/issue-14564.rs [deleted file]
src/test/run-pass/issue-14919.rs
src/test/run-pass/issue-16819.rs [new file with mode: 0644]
src/test/run-pass/issue-17336.rs [new file with mode: 0644]
src/test/run-pass/issue-21410.rs [new file with mode: 0644]
src/test/run-pass/issue-21922.rs [new file with mode: 0644]
src/test/run-pass/issue-22403.rs [new file with mode: 0644]
src/test/run-pass/issue-22781.rs [new file with mode: 0644]
src/test/run-pass/issue-22814.rs [new file with mode: 0644]
src/test/run-pass/issue-23036.rs [new file with mode: 0644]
src/test/run-pass/issue-23891.rs [new file with mode: 0644]
src/test/run-pass/issue-24085.rs
src/test/run-pass/issue-24389.rs [new file with mode: 0644]
src/test/run-pass/issue-24533.rs [new file with mode: 0644]
src/test/run-pass/issue-24805-dropck-itemless.rs
src/test/run-pass/issue-24956.rs [new file with mode: 0644]
src/test/run-pass/issue-24972.rs [new file with mode: 0644]
src/test/run-pass/issue-25439.rs [new file with mode: 0644]
src/test/run-pass/issue-25693.rs [new file with mode: 0644]
src/test/run-pass/issue-26095.rs [new file with mode: 0644]
src/test/run-pass/issue-26905.rs [new file with mode: 0644]
src/test/run-pass/issue-27105.rs [new file with mode: 0644]
src/test/run-pass/issue-27320.rs [new file with mode: 0644]
src/test/run-pass/issue-28189.rs [new file with mode: 0644]
src/test/run-pass/issue-28279.rs [new file with mode: 0644]
src/test/run-pass/issue-28561.rs [new file with mode: 0644]
src/test/run-pass/issue-28676.rs [new file with mode: 0644]
src/test/run-pass/issue-28822.rs [new file with mode: 0644]
src/test/run-pass/issue-28839.rs [new file with mode: 0644]
src/test/run-pass/issue-28936.rs [new file with mode: 0644]
src/test/run-pass/issue-28983.rs [new file with mode: 0644]
src/test/run-pass/issue-28999.rs [new file with mode: 0644]
src/test/run-pass/issue-29037.rs [new file with mode: 0644]
src/test/run-pass/issue-29048.rs [new file with mode: 0644]
src/test/run-pass/issue-29166.rs [new file with mode: 0644]
src/test/run-pass/issue-2935.rs
src/test/run-pass/issue-29746.rs [new file with mode: 0644]
src/test/run-pass/issue-30081.rs [new file with mode: 0644]
src/test/run-pass/issue-5060.rs
src/test/run-pass/issue28498-must-work-ex1.rs [new file with mode: 0644]
src/test/run-pass/issue28498-must-work-ex2.rs [new file with mode: 0644]
src/test/run-pass/issue28498-ugeh-ex1.rs [new file with mode: 0644]
src/test/run-pass/issue28498-ugeh-with-lifetime-param.rs [new file with mode: 0644]
src/test/run-pass/issue28498-ugeh-with-passed-to-fn.rs [new file with mode: 0644]
src/test/run-pass/issue28498-ugeh-with-trait-bound.rs [new file with mode: 0644]
src/test/run-pass/lambda-var-hygiene.rs
src/test/run-pass/new-box-syntax.rs
src/test/run-pass/pushpop-unsafe-okay.rs [deleted file]
src/test/run-pass/regions-early-bound-trait-param.rs
src/test/run-pass/sepcomp-cci.rs
src/test/run-pass/shift-near-oflo.rs
src/test/run-pass/sync-send-iterators-in-libcollections.rs
src/test/run-pass/trait-object-generics.rs
src/test/run-pass/unary-minus-suffix-inference.rs
src/test/run-pass/vec_cycle.rs
src/test/run-pass/vec_cycle_wrapped.rs
src/test/run-pass/wrapping-int-api.rs
src/test/run-pass/x86stdcall2.rs
src/test/rustdoc/hidden-line.rs

index 310a91b2d16fdbe0d0034333497dd49ef0d864d7..d5db7e3310ce1fa5f2209918185c892c1883d64b 100644 (file)
@@ -9,7 +9,9 @@ Aaron Todd <github@opprobrio.us>
 Aaron Turon <aturon@mozilla.com>
 Aaron Weiss <aaronweiss74@gmail.com>
 Abhishek Chanda <abhishek.becs@gmail.com>
+Adam Badawy <adambada@buffalo.edu>
 Adam Bozanich <adam.boz@gmail.com>
+Adam Crume <adamcrume@gmail.com>
 Adam Heins <mail@adamheins.com>
 Adam Jacob <adam@opscode.com>
 Adam Roben <adam@roben.org>
@@ -30,8 +32,10 @@ Alan Cutter <alancutter@chromium.org>
 Alan Williams <mralert@gmail.com>
 Aleksander Balicki <balicki.aleksander@gmail.com>
 Aleksandr Koshlo <sash7ko@gmail.com>
+Aleksey Kladov <aleksey.kladov@gmail.com>
 Alexander Artemenko <svetlyak.40wt@gmail.com>
 Alexander Bliskovsky <alexander.bliskovsky@gmail.com>
+Alexander Bulaev <aleks.bulaev@gmail.com>
 Alexander Campbell <alexanderhcampbell@gmail.com>
 Alexander Chernyakhovsky <achernya@mit.edu>
 Alexander Korolkov <alexander.korolkov@gmail.com>
@@ -42,19 +46,25 @@ Alexandre Gagnon <alxgnon@gmail.com>
 Alexandros Tasos <sdi1100085@di.uoa.gr>
 Alex Burka <durka42+github@gmail.com>
 Alex Crichton <alex@alexcrichton.com>
+AlexDenisov <1101.debian@gmail.com>
 Alexei Sholik <alcosholik@gmail.com>
 Alex Gaynor <alex.gaynor@gmail.com>
 Alexis Beingessner <a.beingessner@gmail.com>
 Alex Lyon <arcterus@mail.com>
 Alex Newman <posix4e@gmail.com>
+Alex Ozdemir <aozdemir@hmc.edu>
 Alex Quach <alex@clinkle.com>
 Alex Rønne Petersen <alex@lycus.org>
 Alex Stokes <r.alex.stokes@gmail.com>
 Alex Whitney <aw1209@ic.ac.uk>
 Alfie John <alfie@alfie.wtf>
+Alfie John <alfiej@fastmail.fm>
 Alisdair Owens <awo101@zepler.net>
 Ali Smesseim <smesseim.ali@gmail.com>
 Aljaž "g5pw" Srebrnič <a2piratesoft@gmail.com>
+Amanieu d'Antras <amanieu@gmail.com>
+Amit Aryeh Levy <amit@amitlevy.com>
+Amit Saha <amitsaha@users.noreply.github.com>
 Amol Mundayoor <amol.com@gmail.com>
 Amy Unger <amy.e.unger@gmail.com>
 Anatoly Ikorsky <aikorsky@gmail.com>
@@ -65,7 +75,9 @@ Andreas Gal <gal@mozilla.com>
 Andreas Martens <andreasm@fastmail.fm>
 Andreas Neuhaus <zargony@zargony.com>
 Andreas Ots <andreasots@gmail.com>
+Andreas Sommer <andreas.sommer87@googlemail.com>
 Andreas Tolfsen <ato@mozilla.com>
+Andre Bogus <bogusandre@gmail.com>
 Andrei Formiga <archimedes_siracusa@hotmail.com>
 Andrei Oprea <andrei.br92@gmail.com>
 Andrew Barchuk <raindev@icloud.com>
@@ -82,14 +94,18 @@ Andrew Poelstra <asp11@sfu.ca>
 Andrew Seidl <dev@aas.io>
 Andrew Straw <strawman@astraw.com>
 Andrew Wagner <drewm1980@gmail.com>
+androm3da <brian.cain@gmail.com>
 Andrzej Janik <vosen@vosen.pl>
 Andy Caldwell <andrew.caldwell@metaswitch.com>
 Andy Grover <agrover@redhat.com>
+angelsl <hidingfromhidden@gmail.com>
 Angus Lees <gus@inodes.org>
 Anthony Juckel <ajuckel@gmail.com>
 Anton Löfgren <anton.lofgren@gmail.com>
 Antti Keränen <detegr@gmail.com>
+aochagavia <aochagavia92@gmail.com>
 Aram Visser <aramvisser@gmail.com>
+arcnmx <arcnmx@users.noreply.github.com>
 Arcterus <Arcterus@mail.com>
 Areski Belaid <areski@gmail.com>
 Ariel Ben-Yehuda <arielb1@mail.tau.ac.il>
@@ -99,9 +115,11 @@ Armin Preiml <apreiml@strohwolke.at>
 Armin Ronacher <armin.ronacher@active-4.com>
 Arpad Borsos <arpad.borsos@googlemail.com>
 Artem <artemciy@gmail.com>
+Artem Shitov <artemshitov@yandex-team.ru>
 Arthur Liao <arthurtw8@gmail.com>
 arthurprs <arthurprs@gmail.com>
 arturo <arturo@openframeworks.cc>
+Ashkan Kiani <ashkan.k.kiani@gmail.com>
 Ashok Gautham <ScriptDevil@gmail.com>
 Augusto Hack <hack.augusto@gmail.com>
 auREAX <mark@xn--hwg34fba.ws>
@@ -113,8 +131,11 @@ Avdi Grimm <avdi@avdi.org>
 awlnx <alecweber1994@gmail.com>
 Axel Viala <axel.viala@darnuria.eu>
 Aydin Kim <ladinjin@hanmail.net>
+b1nd <clint.ryan3@gmail.com>
 bachm <Ab@vapor.com>
+Barosl LEE <github@barosl.com>
 Barosl Lee <vcs@barosl.com>
+Bastien Dejean <nihilhill@gmail.com>
 bcoopers <coopersmithbrian@gmail.com>
 Ben Alpert <ben@benalpert.com>
 benaryorg <binary@benary.org>
@@ -133,19 +154,24 @@ Benjamin Peterson <benjamin@python.org>
 Ben Kelly <ben@wanderview.com>
 Ben Noordhuis <info@bnoordhuis.nl>
 Ben Sago <ogham@users.noreply.github.com>
+benshu <benshu@benshu.de>
+Ben S <ogham@users.noreply.github.com>
 Ben Striegel <ben.striegel@gmail.com>
+Bhargav Patel <bhargavrpatel@users.noreply.github.com>
 Bheesham Persaud <bheesham123@hotmail.com>
 Bilal Husain <bilal@bilalhusain.com>
 Bill Fallon <bill.fallon@robos.li>
 Bill Myers <bill_myers@outlook.com>
+billpmurphy <billpmurphy92@gmail.com>
 Bill Wendling <wendling@apple.com>
 Birunthan Mohanathas <birunthan@mohanathas.com>
 Björn Steinbrink <bsteinbr@gmail.com>
+blackbeam <aikorsky@gmail.com>
 blake2-ppc <ulrik.sverdrup@gmail.com>
 Blake Loring <Blake.Loring@ig.com>
-bluss <bluss>
 bluss <bluss@users.noreply.github.com>
-Boris Egorov <egorov@linux.com>
+bombless <bombless@126.com>
+Boris Egorov <jightuse@gmail.com>
 bors <bors@rust-lang.org>
 Bouke van der Bijl <boukevanderbijl@gmail.com>
 Brad King <brad.king@kitware.com>
@@ -169,10 +195,14 @@ Brian Leibig <brian@brianleibig.com>
 Brian Quinlan <brian@sweetapp.com>
 Brody Holden <brody.holden.r@gmail.com>
 Bruno de Oliveira Abinader <bruno.d@partner.samsung.com>
+Bruno Tavares <connect+github@bltavares.com>
 Bryan Dunsmore <dunsmoreb@gmail.com>
+Bryce Van Dyk <bryce@vandyk.net.nz>
 Byron Williams <byron@112percent.com>
 Cadence Marseille <cadencemarseille@gmail.com>
+caipre <platt.nicholas@gmail.com>
 Caitlin Potter <snowball@defpixel.com>
+Cameron Sun <cameron.csun@gmail.com>
 Cameron Zwarich <zwarich@mozilla.com>
 Camille Roussel <camille@rousselfamily.com>
 Camille TJHOA <camille.tjhoa@outlook.com>
@@ -180,18 +210,25 @@ Cam Jackson <camjackson89@gmail.com>
 Carl-Anton Ingmarsson <mail@carlanton.se>
 Carl Lerche <me@carllerche.com>
 Carlos Galarza <carloslfu@gmail.com>
+Carlos Liam <carlos@aarzee.me>
+Carlos <toqueteos@gmail.com>
 Carol (Nichols || Goulding) <carol.nichols@gmail.com>
 Carol Willing <carolcode@willingconsulting.com>
 Carter Hinsley <carterhinsley@gmail.com>
 Carter Tazio Schonwald <carter.schonwald@gmail.com>
 CarVac <c.lo.to.da.down.lo@gmail.com>
 Caspar Krieger <caspar@asparck.com>
+Cesar Eduardo Barros <cesarb@cesarb.eti.br>
+Charlotte Spencer <charlottelaspencer@gmail.com>
 Chase Southwood <chase.southwood@gmail.com>
 Ches Martin <ches@whiskeyandgrits.net>
-chitra
+chitra <bogus>
 Chloe <5paceToast@users.noreply.github.com>
+Chris C Cerami <chrisccerami@users.noreply.github.com>
 Chris Double <chris.double@double.co.nz>
+Chris Drake <cjdrake@gmail.com>
 Chris Hellmuth <chellmuth@gmail.com>
+Chris Krycho <chris@krycho.com>
 Chris Morgan <me@chrismorgan.info>
 Chris Nixon <chris.nixon@sigma.me.uk>
 Chris Peterson <cpeterson@mozilla.com>
@@ -205,6 +242,7 @@ Christian Weinz <christian@madez.de>
 Christoph Burgdorf <christoph.burgdorf@bvsn.org>
 Christopher Bergqvist <spambox0@digitalpoetry.se>
 Christopher Chambers <chris.chambers@peanutcode.com>
+christopherdumas <christopherdumas@me.com>
 Christopher Kendell <ckendell@outlook.com>
 Chris Wong <lambda.fairy@gmail.com>
 chromatic <chromatic@wgz.org>
@@ -220,18 +258,25 @@ Cole Mickens <cole.mickens@gmail.com>
 Cole Reynolds <cpjreynolds@gmail.com>
 Colin Davidson <colrdavidson@gmail.com>
 Colin Sherratt <colin.sherratt@gmail.com>
+Colin Wallace <wallacoloo@gmail.com>
 Colin Walters <walters@verbum.org>
 comex <comexk@gmail.com>
 Conrad Kleinespel <conradk@conradk.com>
+corentih <corentin.henry@alcatel-lucent.com>
+Corentin Henry <corentinhenry@gmail.com>
 Corey Farwell <coreyf+rust@rwell.org>
 Corey Ford <corey@coreyford.name>
 Corey Richardson <corey@octayn.net>
 Cornel Punga <cornel.punga@gmail.com>
+Craig Hills <chills@gmail.com>
 crhino <piraino.chris@gmail.com>
 Cristian Kubis <cristian.kubis@tsunix.de>
 Cristi Burcă <scribu@gmail.com>
+Cristi Cobzarenco <cristi.cobzarenco@gmail.com>
 critiqjo <john.ch.fr@gmail.com>
 Cruz Julian Bishop <cruzjbishop@gmail.com>
+Daan Rijks <daanrijks@gmail.com>
+Dabo Ross <daboross@daboross.net>
 Damian Gryski <damian@gryski.com>
 Damien Grassart <damien@grassart.com>
 Damien Radtke <dradtke@channeliq.com>
@@ -242,11 +287,13 @@ Dan Callahan <dan.callahan@gmail.com>
 Dan Connolly <dckc@madmode.com>
 Daniel Albert <albert_daniel@t-online.de>
 Daniel Brooks <db48x@db48x.net>
+Daniel Carral <dan@dcarral.org>
 Daniel Fagnan <dnfagnan@gmail.com>
 Daniel Farina <daniel@fdr.io>
 Daniel Griffen <daniel@dgriffen.com>
 Daniel Grunwald <daniel@danielgrunwald.de>
 Daniel Hofstetter <daniel.hofstetter@42dh.com>
+Daniel Keep <daniel.keep@gmail.com>
 Daniel Lobato García <elobatocs@gmail.com>
 Daniel Luz <dev@mernen.com>
 Daniel MacDougall <dmacdougall@gmail.com>
@@ -255,9 +302,12 @@ Daniel Patterson <dbp@riseup.net>
 Daniel Raloff <draloff@side2.com>
 Daniel Ralston <Wubbulous@gmail.com>
 Daniel Ramos <dan@daramos.com>
+Daniel Rollins <drollins@financialforce.com>
 Daniel Rosenwasser <DanielRosenwasser@gmail.com>
+Daniel Trebbien <dtrebbien@gmail.com>
 Daniel Ursache Dogariu <contact@danniel.net>
 Daniil Smirnov <danslapman@gmail.com>
+Danilo Bargen <mail@dbrgn.ch>
 Dan Luu <danluu@gmail.com>
 Dan Schatzberg <schatzberg.dan@gmail.com>
 Dan W. <1danwade@gmail.com>
@@ -265,11 +315,13 @@ Dan Yang <dsyang@fb.com>
 Darin Morrison <darinmorrison+git@gmail.com>
 darkf <lw9k123@gmail.com>
 Darrell Hamilton <darrell.noice@gmail.com>
+Dato Simó <dato@net.com.org.es>
 Dave Herman <dherman@mozilla.com>
 Dave Hodder <dmh@dmh.org.uk>
 Dave Huseby <dhuseby@mozilla.com>
 David Campbell <dcampbell24@gmail.com>
 David Creswick <dcrewi@gyrae.net>
+David Elliott <david@gophilosophie.com>
 David Forsythe <dforsythe@gmail.com>
 David Halperin <halperin.dr@gmail.com>
 David King <dave@davbo.org>
@@ -279,17 +331,21 @@ David Manescu <david.manescu@gmail.com>
 David Rajchenbach-Teller <dteller@mozilla.com>
 David Reid <dreid@dreid.org>
 David Renshaw <dwrenshaw@gmail.com>
+David Ripton <dripton@ripton.net>
 David Ross <daboross@daboross.net>
 David Stygstra <david.stygstra@gmail.com>
+David Szotten <davidszotten@gmail.com>
 David Vazgenovich Shakaryan <dvshakaryan@gmail.com>
 David Voit <david.voit@gmail.com>
 Davis Silverman <sinistersnare@gmail.com>
 defuz <defuz.net@gmail.com>
 Denis Defreyne <denis.defreyne@stoneship.org>
+DenisKolodin <DenisKolodin@gmail.com>
 Derecho <derecho@sector5d.org>
 Derek Chiang <derekchiang93@gmail.com>
 Derek Guenther <dguenther9@gmail.com>
 Derek Harland <derek.harland@finq.co.nz>
+Devon Hollowood <devonhollowood@gmail.com>
 dgoon <dgoon@dgoon.net>
 diaphore <diaphore@gmail.com>
 Diego Giagio <diego@giagio.com>
@@ -311,10 +367,13 @@ Dmitry Vasiliev <dima@hlabs.org>
 Dominick Allen <dominick.allen1989@gmail.com>
 Dominic van Berkel <dominic@baudvine.net>
 Dominik Inführ <dominik.infuehr@gmail.com>
+Dongie Agnir <dongie.agnir@gmail.com>
+Dong Zhou <dong.zhou.08@gmail.com>
 Do Nhat Minh <mrordinaire@gmail.com>
 donkopotamus <general@chocolate-fish.com>
 Donovan Preston <donovanpreston@gmail.com>
 Don Petersen <don@donpetersen.net>
+Doug Goldstein <cardoe@cardoe.com>
 Douglas Young <rcxdude@gmail.com>
 Drew Crawford <drew@sealedabstract.com>
 Drew Willcoxon <adw@mozilla.com>
@@ -322,8 +381,10 @@ Duane Edwards <mail@duaneedwards.net>
 Duncan Regan <duncanregan@gmail.com>
 Dylan Braithwaite <dylanbraithwaite1@gmail.com>
 Dylan Ede <dylanede@googlemail.com>
+Dylan McKay <dylanmckay34@gmail.com>
 Dzmitry Malyshau <kvarkus@gmail.com>
 Earl St Sauver <estsauver@gmail.com>
+ebadf <brian.cain@gmail.com>
 econoplas <econoplas@gmail.com>
 Eduard Bopp <eduard.bopp@aepsil0n.de>
 Eduard Burtescu <edy.burt@gmail.com>
@@ -339,12 +400,14 @@ Elliott Slaughter <elliottslaughter@gmail.com>
 Elly Fong-Jones <elly@leptoquark.net>
 elszben <notgonna@tellyou>
 emanueLczirai <emanueLczirai@cryptoLab.net>
+Emanuel Czirai <zazdxscf@gmail.com>
 Emanuel Rylke <ema-fox@web.de>
 Emeliov Dmitrii <demelev1990@gmail.com>
 Emilio Cobos Álvarez <ecoal95@gmail.com>
 Emily Dunham <edunham@mozilla.com>
 Eric Allen <ericpallen@gmail.com>
 Eric Biggers <ebiggers3@gmail.com>
+Eric Findlay <e.findlay@protonmail.com>
 Eric Holk <eric.holk@gmail.com>
 Eric Holmes <eric@ejholmes.net>
 Eric Kidd <git@randomhacks.net>
@@ -354,6 +417,7 @@ Eric Martin <e.a.martin1337@gmail.com>
 Eric Platon <eric.platon@waku-waku.ne.jp>
 Eric Reed <ecreed@cs.washington.edu>
 Eric Ye <me@ericye16.com>
+Erik Davidson <erik@erikd.org>
 Erik Lyon <elyon001@local.fake>
 Erik Michaels-Ober <sferik@gmail.com>
 Erik Price <erik.price16@gmail.com>
@@ -366,8 +430,9 @@ Eunchong Yu <kroisse@gmail.com>
 Eunji Jeong <eun-ji.jeong@samsung.com>
 Evan Klitzke <evan@eklitzke.org>
 Evan McClanahan <evan@evanmcc.com>
-Evgeny Sologubov
+Evgeny Sologubov <bogus>
 Fabian Deutsch <fabian.deutsch@gmx.de>
+Fabiano Beselga <fabianobeselga@gmail.com>
 Fabrice Desré <fabrice@desre.org>
 FakeKane <andrewyli@gmail.com>
 Falco Hirschenberger <falco.hirschenberger@gmail.com>
@@ -378,7 +443,7 @@ Felix S. Klock II <pnkfelix@pnkfx.org>
 fenduru <fenduru@users.noreply.github.com>
 Fenhl <fenhl@fenhl.net>
 Filip Szczepański <jazz2rulez@gmail.com>
-Flaper Fesp <flaper87@gmail.com>
+Flavio Percoco <flaper87@gmail.com>
 flo-l <lacknerflo@gmail.com>
 Florian Gilcher <florian.gilcher@asquera.de>
 Florian Hahn <flo@fhahn.com>
@@ -418,11 +483,13 @@ Germano Gabbianelli <tyrion@users.noreply.github.com>
 Gil Cottle <rc@redtown.org>
 Gioele Barabucci <gioele@svario.it>
 github-monoculture <eocene@gmx.com>
+GlacJAY <glacjay@gmail.com>
 Gleb Kozyrev <gleb@gkoz.com>
+glendc <decauwsemaecker.glen@gmail.com>
 Glenn Willen <gwillen@nerdnet.org>
 Gonçalo Cabrita <_@gmcabrita.com>
 Grahame Bowland <grahame@angrygoats.net>
-Graham Fawcett <graham.fawcett@gmail.com>
+Graham Fawcett <fawcett@uwindsor.ca>
 Graydon Hoare <graydon@pobox.com>
 Greg Chapple <gregchapple1@gmail.com>
 Grigoriy <ohaistarlight@gmail.com>
@@ -447,6 +514,7 @@ Honza Strnad <hanny.strnad@gmail.com>
 Huachao Huang <huachao.huang@gmail.com>
 Hugo Jobling <hello@thisishugo.com>
 Hugo van der Wijst <hugo@wij.st>
+Hunan Rostomyan <hunan131@gmail.com>
 Huon Wilson <dbau.pp+github@gmail.com>
 Hyeon Kim <simnalamburt@gmail.com>
 Ian Connolly <iconnolly@mozilla.com>
@@ -454,22 +522,30 @@ Ian Daniher <it.daniher@gmail.com>
 Ian D. Bollinger <ian.bollinger@gmail.com>
 Ignacio Corderi <icorderi@msn.com>
 Igor Bukanov <igor@mir2.org>
+Igor Shuvalov <i.s.shuvalov@gmail.com>
 Igor Strebezhev <xamgore@ya.ru>
 Ilya Dmitrichenko <ilya@xively.com>
 Ilyong Cho <ilyoan@gmail.com>
 Ingo Blechschmidt <iblech@web.de>
 inrustwetrust <inrustwetrust@users.noreply.github.com>
+Irving A.J. Rivas Z. <axel.rivas@gmail.com>
 Isaac Aggrey <isaac.aggrey@gmail.com>
 Isaac Dupree <antispam@idupree.com>
 Isaac Ge <acgtyrant@gmail.com>
 Ivan Enderlin <ivan.enderlin@hoa-project.net>
+Ivan Ivaschenko <defuz.net@gmail.com>
+Ivan Jager <aij+git@mrph.org>
+Ivan Kozik <ivan@ludios.org>
 Ivano Coppola <rgbfirefox@gmail.com>
 Ivan Petkov <ivanppetkov@gmail.com>
 Ivan Radanov Ivanov <ivanradanov@yahoo.co.uk>
+Ivan Stankovic <pokemon@fly.srk.fer.hr>
 Ivan Ukhov <ivan.ukhov@gmail.com>
 Iven Hsu <ivenvd@gmail.com>
+Jack Fransham <moonfudgeman@hotmail.co.uk>
 Jack Heizer <jack.heizer@gmail.com>
 Jack Moffitt <jack@metajack.im>
+Jack Wilson <jack.wilson.v@gmail.com>
 Jacob Edelman <edelman.jd@gmail.com>
 Jacob Harris Cryer Kragh <jhckragh@gmail.com>
 Jacob Hegna <jacobhegna@gmail.com>
@@ -481,14 +557,18 @@ Jake Hickey <empty@cqdr.es>
 Jake Kaufman <theevocater@gmail.com>
 Jake Kerr <kodafox@gmail.com>
 Jake Scott <jake.net@gmail.com>
+Jake Shadle <jake.shadle@frostbite.com>
+Jake Worth <jakeworth82@gmail.com>
 Jakub Bukaj <jakub@jakub.cc>
 Jakub Vrána <jakub@vrana.cz>
 Jakub Wieczorek <jakubw@jakubw.net>
+James Bell <james.bell@gmail.com>
 James Deng <cnjamesdeng@gmail.com>
 James Hurst <jamesrhurst@users.noreply.github.com>
 James Lal <james@lightsofapollo.com>
 James Laverack <james@jameslaverack.com>
 jamesluke <jamesluke@users.noreply.github.com>
+James McGlashan <github@darkfox.id.au>
 James Miller <bladeon@gmail.com>
 James Perry <james.austin.perry@gmail.com>
 James Rowe <jroweboy@gmail.com>
@@ -518,6 +598,7 @@ Jay True <glacjay@gmail.com>
 J Bailey <jj2baile@uwaterloo.ca>
 jbranchaud <jbranchaud@gmail.com>
 J.C. Moyer <jmoyer1992@gmail.com>
+Jean Maillard <jeanm@users.noreply.github.com>
 Jeaye <jeaye@arrownext.com>
 Jed Davis <jld@panix.com>
 Jed Estep <aje@jhu.edu>
@@ -527,6 +608,7 @@ Jeff Belgum <jeffbelgum@gmail.com>
 Jeff Muizelaar <jmuizelaar@mozilla.com>
 Jeff Olson <olson.jeffery@gmail.com>
 Jeff Parsons <jeffdougson@gmail.com>
+Jeffrey Seyfried <jeffrey.seyfried@gmail.com>
 Jeffrey Yasskin <jyasskin@gmail.com>
 Jelte Fennema <github-tech@jeltef.nl>
 Jens Nockert <jens@nockert.se>
@@ -539,10 +621,11 @@ Jesse Ray <jesse@localhost.localdomain>
 Jesse Ruderman <jruderman@gmail.com>
 Jessy Diamond Exum <jessy.diamondman@gmail.com>
 Jesús Espino <jespinog@gmail.com>
+Jethro Beekman <jethro@jbeekman.nl>
 jethrogb <github@jbeekman.nl>
 Jexell <Jexell@users.noreply.github.com>
 Jihyeok Seo <me@limeburst.net>
-Jihyun Yu <j.yu@navercorp.com>
+Jihyun Yu <jihyun@nclab.kaist.ac.kr>
 Jim Apple <jbapple+rust@google.com>
 Jim Blandy <jimb@red-bean.com>
 Jimmie Elvenmark <flugsio@gmail.com>
@@ -554,13 +637,14 @@ J. J. Weber <jjweber@gmail.com>
 jmgrosen <jmgrosen@gmail.com>
 jmu303 <muj@bc.edu>
 João Oliveira <hello@jxs.pt>
+joaoxsouls <joaoxsouls@gmail.com>
 Joe Pletcher <joepletcher@gmail.com>
 Joe Schafer <joe@jschaf.com>
 Johannes Hoff <johshoff@gmail.com>
 Johannes Löthberg <johannes@kyriasis.com>
 Johannes Muenzel <jmuenzel@gmail.com>
 Johannes Oertel <johannes.oertel@uni-due.de>
-Johann Hofmann <git@johann-hofmann.com>
+Johann Hofmann <mail@johann-hofmann.com>
 Johann Tuffe <tafia973@gmail.com>
 John Albietz <inthecloud247@gmail.com>
 John Barker <jebarker@gmail.com>
@@ -575,10 +659,12 @@ John Louis Walker <injyuw@gmail.com>
 John Schmidt <john.schmidt.h@gmail.com>
 John Simon <john@johnsoft.com>
 John Talling <inrustwetrust@users.noreply.github.com>
+John Thomas <thomas07@vt.edu>
 John Van Enk <vanenkj@gmail.com>
 John Zhang <john@zhang.io>
 joliv <joliv@users.noreply.github.com>
 Jonas Hietala <tradet.h@gmail.com>
+Jonas Schievink <jonas@schievink.net>
 Jonathan Bailey <jbailey@mozilla.com>
 Jonathan Boyett <jonathan@failingservers.com>
 Jonathan Hansford <dangthrimble@hansfords.net>
@@ -593,25 +679,32 @@ Joonas Javanainen <joonas.javanainen@gmail.com>
 Jordan Humphreys <mrsweaters@users.noreply.github.com>
 Jordan Woehr <jordanwoehr@gmail.com>
 Jordi Boggiano <j.boggiano@seld.be>
-Jorge Aparicio <japaricious@gmail.com>
+Jorge Aparicio <japaric@linux.com>
 Jorge Israel Peña <jorge.israel.p@gmail.com>
 Joris Rehm <joris.rehm@wakusei.fr>
 Jormundir <Chaseph@gmail.com>
+Jørn Lode <jlode90@gmail.com>
 Jose Narvaez <jnarvaez@zendesk.com>
+Joseph Caudle <joseph@josephcaudle.com>
 Joseph Crail <jbcrail@gmail.com>
 Joseph Martin <pythoner6@gmail.com>
 Joseph Rushton Wakeling <joe@webdrake.net>
+Josh Austin <josh.austin@gmail.com>
 Josh Haberman <jhaberman@gmail.com>
 Josh Matthews <josh@joshmatthews.net>
 Josh Stone <cuviper@gmail.com>
 Josh Triplett <josh@joshtriplett.org>
 Joshua Clark <joshua.clark@txstate.edu>
+Joshua Holmer <holmerj@uindy.edu>
 Joshua Landau <joshua@landau.ws>
 Joshua Wise <joshua@joshuawise.com>
 Joshua Yanovski <pythonesque@gmail.com>
+jotomicron <jotomicron@gmail.com>
 JP-Ellis <coujellis@gmail.com>
 JP Sugarbroad <jpsugar@google.com>
+jrburke <jrburke@gmail.com>
 jrincayc <jrincayc@users.noreply.github.com>
+J. Ryan Stinnett <jryans@gmail.com>
 Julia Evans <julia@jvns.ca>
 Julian Orth <ju.orth@gmail.com>
 Julian Viereck <julian.viereck@gmail.com>
@@ -640,12 +733,15 @@ Kevin Murphy <kemurphy.cmu@gmail.com>
 Kevin Rauwolf <sweetpea-git@tentacle.net>
 Kevin Walter <kevin.walter.private@googlemail.com>
 Kevin Yap <me@kevinyap.ca>
+Kevin Yeh <kevinyeah@utexas.edu>
 kgv <mail@kgv.name>
+kickinbahk <kickinbahk@gmail.com>
 Kieran Hunt <kieran.hunt92@gmail.com>
 Kiet Tran <ktt3ja@gmail.com>
 Kim Røen <kim@pam.no>
 kjpgit <kjpgit@users.noreply.github.com>
 klutzy <klutzytheklutzy@gmail.com>
+Kohei Hasegawa <ameutau@gmail.com>
 KokaKiwi <kokakiwi+rust@kokakiwi.net>
 korenchkin <korenchkin2@gmail.com>
 Kornel Lesiński <kornel@geekhood.net>
@@ -657,6 +753,8 @@ Kubilay Kocak <koobs@users.noreply.github.com>
 kulakowski <george.kulakowski@gmail.com>
 kwantam <kwantam@gmail.com>
 Kyeongwoon Lee <kyeongwoon.lee@samsung.com>
+Kyle Mayes <kyle@mayeses.com>
+Kyle Robinson Young <kyle@dontkry.com>
 Lai Jiangshan <laijs@cn.fujitsu.com>
 Lars Bergstrom <lbergstrom@mozilla.com>
 Laurence Tratt <laurie@tratt.net>
@@ -666,6 +764,7 @@ Lawrence Velázquez <larryv@alum.mit.edu>
 Leah Hanson <astrieanna@gmail.com>
 Lee Aronson <lee@libertad.ucsd.edu>
 Lee Jeffery <leejeffery@gmail.com>
+Lee Jenkins <cljenkins9@gmail.com>
 Lee Wondong <wdlee91@gmail.com>
 Leif Arne Storset <leifarne@storset.net>
 LemmingAvalanche <haugsbakk@yahoo.no>
@@ -678,6 +777,7 @@ Liam Monahan <liam@monahan.io>
 Liigo Zhuang <com.liigo@gmail.com>
 Lindsey Kuper <lindsey@composition.al>
 Lionel Flandrin <lionel.flandrin@parrot.com>
+llogiq <bogusandre@gmail.com>
 Logan Chien <tzuhsiang.chien@gmail.com>
 Loïc Damien <loic.damien@dzamlo.ch>
 Lorenz <lorenzb@student.ethz.ch>
@@ -701,7 +801,10 @@ Makoto Kato <m_kato@ga2.so-net.ne.jp>
 Makoto Nakashima <makoto.nksm+github@gmail.com>
 Manish Goregaokar <manishsmail@gmail.com>
 Manuel Hoffmann <manuel@polythematik.de>
+Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
 marcell <marcell.pardavi@gmail.com>
+Marcello Seri <marcello.seri@gmail.com>
+Marcell Pardavi <marcell.pardavi@gmail.com>
 Marcel Müller <neikos@neikos.email>
 Marcel Rodrigues <marcelgmr@gmail.com>
 Marcus Klaas <mail@marcusklaas.nl>
@@ -712,6 +815,7 @@ Mário Feroldi <thelost-t@live.com>
 Mark Buer <mark.buer@booktrack.com>
 Mark Lacey <641@rudkx.com>
 Mark Mossberg <mark.mossberg@gmail.com>
+Marko Lalic <marko.lalic@gmail.com>
 Mark Rowe <mrowe@bdash.net.nz>
 Mark Sinclair <mark.edward.x@gmail.com>
 Markus Siemens <siemens1993@gmail.com>
@@ -721,9 +825,11 @@ Mark Vian <mrv.caseus@gmail.com>
 Martin DeMello <martindemello@gmail.com>
 Martin Olsson <martin@minimum.se>
 Martin Pool <mbp@sourcefrog.net>
+Martin Wernstål <m4rw3r@gmail.com>
 Marti Raudsepp <marti@juffo.org>
 Marvin Löbel <loebel.marvin@gmail.com>
 masklinn <github.com@masklinn.net>
+Matěj Grabovský <mgrabovsky@yahoo.com>
 Matej Lach <matej.lach@gmail.com>
 Mateusz Czapliński <czapkofan@gmail.com>
 Mathieu David <mathieudavid@mathieudavid.org>
@@ -740,7 +846,9 @@ Matthew Auld <matthew.auld@intel.com>
 Matthew Iselin <matthew@theiselins.net>
 Matthew McPherrin <matthew@mcpherrin.ca>
 Matthew O'Connor <thegreendragon@gmail.com>
+Matthias Bussonnier <bussonniermatthias@gmail.com>
 Matthias Einwag <matthias.einwag@live.com>
+Matthias Kauer <mk.software@zuez.org>
 Matthijs Hofstra <thiezz@gmail.com>
 Matthijs van der Vleuten <git@zr40.nl>
 Matt McPherrin <git@mcpherrin.ca>
@@ -762,15 +870,18 @@ Michael Alexander <beefsack@gmail.com>
 Michael Arntzenius <daekharel@gmail.com>
 Michael Bebenita <mbebenita@mozilla.com>
 Michael Budde <mbudde@gmail.com>
+Michael Choate <choatemd@miamioh.edu>
 Michael Dagitses <dagitses@google.com>
 Michael Darakananda <pongad@gmail.com>
 Michael Fairley <michaelfairley@gmail.com>
 Michael Gehring <mg@ebfe.org>
+Michael Howell <michael@notriddle.com>
 Michael Kainer <kaini1123@gmail.com>
 Michael Layzell <michael@thelayzells.com>
 Michael Letterle <michael.letterle@gmail.com>
 Michael Macias <zaeleus@gmail.com>
 Michael Matuzak <mmatuzak@gmail.com>
+Michael McConville <mmcconville@mykolab.com>
 Michael Neumann <mneumann@ntecs.de>
 Michael Pankov <work@michaelpankov.com>
 Michael Park <mcypark@gmail.com>
@@ -790,10 +901,12 @@ Mickaël Raybaud-Roig <raybaudroigm@gmail.com>
 Mickaël Salaün <mic@digikod.net>
 Mick Koch <kchmck@gmail.com>
 midinastasurazz <mpavlovsky@gmail.com>
+Mihaly Barasz <klao@nilcons.com>
 Mihnea Dobrescu-Balaur <mihnea@linux.com>
 Mike Boutin <mike.boutin@gmail.com>
 Mike Dilger <mike@efx.co.nz>
 Mike English <mike.english@atomicobject.com>
+Mike Marcacci <mike.marcacci@gmail.com>
 Mike Pedersen <noctune9@gmail.com>
 Mike Robinson <mikeprobinsonuk@gmail.com>
 Mike Sampson <mike@sambodata.com>
@@ -814,6 +927,7 @@ nathan dotz <nathan.dotz@gmail.com>
 Nathan Froyd <froydnj@gmail.com>
 Nathaniel Herman <nherman@post.harvard.edu>
 Nathaniel Theis <nttheis@gmail.com>
+Nathan Kleyn <nathan@nathankleyn.com>
 Nathan Long <nathanmlong@gmail.com>
 Nathan Stoddard <nstodda@purdue.edu>
 Nathan Typanski <ntypanski@gmail.com>
@@ -822,9 +936,11 @@ Nathan Zadoks <nathan@nathan7.eu>
 Neil Pankey <npankey@gmail.com>
 Nelo Onyiah <nelo.onyiah@gmail.com>
 Nelson Chen <crazysim@gmail.com>
+nham <hamann.nick@gmail.com>
 NiccosSystem <niccossystem@gmail.com>
 Nicholas Bishop <nicholasbishop@gmail.com>
 Nicholas Mazzuca <npmazzuca@gmail.com>
+Nicholas Seckar <nseckar@gmail.com>
 Nick Cameron <ncameron@mozilla.com>
 Nick Desaulniers <ndesaulniers@mozilla.com>
 Nick Fitzgerald <fitzgen@gmail.com>
@@ -839,9 +955,11 @@ Niels langager Ellegaard <niels.ellegaard@gmail.com>
 Nif Ward <nif.ward@gmail.com>
 Nikita Pekin <contact@nikitapek.in>
 Niklas Koep <niklas.koep@gmail.com>
+Nikolay Kondratyev <nkondratyev@yandex.ru>
 Niko Matsakis <niko@alum.mit.edu>
 Nils Liberg <nils@nilsliberg.se>
 Nils Winter <nils.winter@gmail.com>
+Niranjan Padmanabhan <niranjan.padmanabhan@cloudera.com>
 noam <noam@clusterfoo.com>
 Noam Yorav-Raphael <noamraph@gmail.com>
 NODA, Kai <nodakai@gmail.com>
@@ -849,25 +967,31 @@ Noufal Ibrahim <noufal@nibrahim.net.in>
 novalis <novalis@novalis.org>
 nsf <no.smile.face@gmail.com>
 nwin <nwin@users.noreply.github.com>
+nxnfufunezn <nxnfufunezn@gmail.com>
 Oak <White-Oak@users.noreply.github.com>
 OGINO Masanori <masanori.ogino@gmail.com>
 OlegTsyba <idethrone1@gmail.com>
-Oliver Schneider <git1984941651981@oli-obk.de>
+Ole Krüger <ole@kru.gr>
+Oliver Middleton <olliemail27@gmail.com>
+Oliver Schneider <oliver.schneider@kit.edu>
 Olivier Saut <osaut@airpost.net>
 olivren <o.renaud@gmx.fr>
 Olle Jonsson <olle.jonsson@gmail.com>
 olombard <lombard-olivier@bbox.fr>
 Or Brostovski <tohava@gmail.com>
 Oren Hazi <oren.hazi@gmail.com>
+Ori Avtalion <ori@avtalion.name>
 Or Neeman <oneeman@gmail.com>
 Orphée Lafond-Lummis <o@orftz.com>
 Orpheus Lummis <o@orpheuslummis.com>
 osa1 <omeragacan@gmail.com>
 O S K Chaitanya <osk@medhas.org>
+Overmind JIANG <p90eri@gmail.com>
 Ožbolt Menegatti <ozbolt.menegatti@gmail.com>
 P1start <rewi-github@whanau.org>
 Pablo Brasero <pablo@pablobm.com>
 Palmer Cox <p@lmercox.com>
+panicbit <panicbit.dev@gmail.com>
 Paolo Falabella <paolo.falabella@gmail.com>
 Parker Moore <parkrmoore@gmail.com>
 Pascal Hertleif <killercup@gmail.com>
@@ -876,6 +1000,7 @@ Patrick Walton <pcwalton@mimiga.net>
 Patrick Yevsukov <patrickyevsukov@users.noreply.github.com>
 Patrik Kårlin <patrik.karlin@gmail.com>
 Paul ADENOT <paul@paul.cx>
+Paul A. Jungwirth <pj@illuminatedcomputing.com>
 Paul Banks <banks@banksdesigns.co.uk>
 Paul Collier <paul@paulcollier.ca>
 Paul Collins <paul@ondioline.org>
@@ -898,6 +1023,7 @@ Peter Elmers <peter.elmers@yahoo.com>
 Peter Hull <peterhull90@gmail.com>
 Peter Marheine <peter@taricorp.net>
 Peter Minten <peter@pminten.nl>
+Peter Reid <peter.d.reid@gmail.com>
 Peter Schuller <peter.schuller@infidyne.com>
 Peter Williams <peter@newton.cx>
 Peter Zotov <whitequark@whitequark.org>
@@ -907,8 +1033,11 @@ Phil Dawes <phil@phildawes.net>
 Philip Munksgaard <pmunksgaard@gmail.com>
 Philipp Brüschweiler <blei42@gmail.com>
 Philipp Gesang <phg42.2a@gmail.com>
+Philipp Matthias Schäfer <philipp.matthias.schaefer@posteo.de>
+Philipp Oppermann <dev@phil-opp.com>
 Phil Ruffwind <rf@rufflewind.com>
 Pierre Baillet <pierre@baillet.name>
+pierzchalski <e.a.pierzchalski@gmail.com>
 Piotr Czarnecki <pioczarn@gmail.com>
 Piotr Jawniak <sawyer47@gmail.com>
 Piotr Szotkowski <chastell@chastell.net>
@@ -916,10 +1045,12 @@ Piotr Zolnierek <pz@anixe.pl>
 Poga Po <poga.bahamut@gmail.com>
 posixphreak <posixphreak@gmail.com>
 Potpourri <pot_pourri@mail.ru>
+Pradeep Kumar <gohanpra@gmail.com>
 Prudhvi Krishna Surapaneni <me@prudhvi.net>
 Przemysław Wesołek <jest@go.art.pl>
 Pyfisch <pyfisch@gmail.com>
 Pyry Kontio <pyry.kontio@drasa.eu>
+Pythoner6 <pythoner6@gmail.com>
 Q.P.Liu <qpliu@yahoo.com>
 qwitwa <qwitwa@gmail.com>
 Rafael Ávila de Espíndola <respindola@mozilla.com>
@@ -933,6 +1064,7 @@ Raphael Catolino <raphael.catolino@gmail.com>
 Raphael Nestler <raphael.nestler@gmail.com>
 Raphael Speyer <rspeyer@gmail.com>
 Raul Gutierrez S <rgs@itevenworks.net>
+Ravi Shankar <wafflespeanut@gmail.com>
 Ray Clanan <rclanan@utopianconcept.com>
 ray glover <ray@rayglover.net>
 reedlepee <reedlepee123@gmail.com>
@@ -942,20 +1074,25 @@ Rémi Audebert <halfr@lse.epita.fr>
 Remi Rampin <remirampin@gmail.com>
 Renato Alves <alves.rjc@gmail.com>
 Renato Riccieri Santos Zannon <renato@rrsz.com.br>
+Renato Zannon <renato@rrsz.com.br>
 Reuben Morais <reuben.morais@gmail.com>
 reus <reusee@ymail.com>
+Reza Akhavan <reza@akhavan.me>
 Ricardo Martins <ricardo@scarybox.net>
 Ricardo M. Correia <rcorreia@wizy.org>
+Ricardo Signes <rjbs@cpan.org>
 Richard Diamond <wichard@vitalitystudios.com>
 Rich Lane <rlane@club.cc.cmu.edu>
 Richo Healey <richo@psych0tik.net>
 Rick Waldron <waldron.rick@gmail.com>
 Ricky Taylor <rickytaylor26@gmail.com>
+Rizky Luthfianto <mrluthfianto@gmail.com>
 rjz <rj@rjzaworski.com>
 Rob Arnold <robarnold@cs.cmu.edu>
 Robert Buonpastore <robert.buonpastore@gmail.com>
 Robert Clipsham <robert@octarineparrot.com>
 Robert Foss <dev@robertfoss.se>
+Robert Gardner <rhg259@nyu.edu>
 Robert Gawdzik <rgawdzik@hotmail.com>
 Robert Irelan <rirelan@gmail.com>
 Robert Knight <robertknight@gmail.com>
@@ -973,6 +1110,7 @@ Ron Dahlgren <ronald.dahlgren@gmail.com>
 Rory O’Kane <rory@roryokane.com>
 Roy Crihfield <rscrihf@gmail.com>
 Roy Frostig <rfrostig@mozilla.com>
+Ruby <hi@ruby.sh>
 Rüdiger Sonderfeld <ruediger@c-plusplus.de>
 rundrop1 <rundrop1@zoho.com>
 Russell Johnston <rpjohnst@gmail.com>
@@ -986,6 +1124,7 @@ Ryan Riginding <marc.riginding@gmail.com>
 Ryan Scheel <ryan.havvy@gmail.com>
 Ryman <haqkrs@gmail.com>
 らいどっと <ryogo.yoshimura@gmail.com>
+Ryo Munakata <afpacket@gmail.com>
 Sae-bom Kim <sae-bom.kim@samsung.com>
 Salem Talha <salem.a.talha@gmail.com>
 saml <saml@users.noreply.github.com>
@@ -1011,14 +1150,17 @@ Sean Patrick Santos <SeanPatrickSantos@gmail.com>
 Sean Stangl <sstangl@mozilla.com>
 Sean T Allen <sean@monkeysnatchbanana.com>
 Sebastian Gesemann <s.gesemann@gmail.com>
+Sebastian Hahn <sebastian@torproject.org>
 Sebastian N. Fernandez <cachobot@gmail.com>
 Sebastian Rasmussen <sebras@gmail.com>
+Sebastian Wicki <gandro@gmx.net>
 Sebastian Zaha <sebastian.zaha@gmail.com>
 Sébastien Chauvel <eichi237@mailoo.org>
 Sébastien Crozet <developer@crozet.re>
 Sébastien Marie <semarie@users.noreply.github.com>
 Sebastien Martini <seb@dbzteam.org>
 Sébastien Paolacci <sebastien.paolacci@gmail.com>
+Seeker14491 <seeker14491@gmail.com>
 Seonghyun Kim <sh8281.kim@samsung.com>
 Seo Sanghyeon <sanxiyn@gmail.com>
 Sergio Benitez <sbenitez@mit.edu>
@@ -1033,12 +1175,14 @@ SiegeLord <slabode@aim.com>
 Simonas Kazlauskas <git@kazlauskas.me>
 Simon Barber-Dueck <sbarberdueck@gmail.com>
 Simon Kern <simon.kern@rwth-aachen.de>
+Simon Mazur <semmaz.box@gmail.com>
 Simon Persson <simon@flaskpost.org>
 Simon Sapin <simon@exyr.org>
 Simon Wollwage <mail.wollwage@gmail.com>
 simplex <theemptystring@gmail.com>
 Sindre Johansen <sindre@sindrejohansen.no>
 sinkuu <sinkuupump@gmail.com>
+skeleten <janpelle.thomson@stud.tu-darmstadt.de>
 Skyler <skyler.lipthay@gmail.com>
 smenardpw <sebastien@knoglr.com>
 Son <leson.phung@gmail.com>
@@ -1047,6 +1191,7 @@ S Pradeep Kumar <gohanpra@gmail.com>
 Squeaky <squeaky_pl@gmx.com>
 startling <tdixon51793@gmail.com>
 Stefan Bucur <stefan.bucur@epfl.ch>
+Stefan O'Rear <stefanor@cox.net>
 Stefan Plantikow <stefan.plantikow@googlemail.com>
 Stepan Koltsov <stepan.koltsov@gmail.com>
 Sterling Greene <sterling.greene@gmail.com>
@@ -1072,7 +1217,9 @@ Taras Shpot <mrshpot@gmail.com>
 tav <tav@espians.com>
 Taylor Hutchison <seanthutchison@gmail.com>
 Ted Horst <ted.horst@earthlink.net>
+Ted Mielczarek <ted@mielczarek.org>
 Tero Hänninen <lgvz@users.noreply.github.com>
+Tero Hänninen <tejohann@kapsi.fi>
 th0114nd <th0114nd@gmail.com>
 Thad Guidry <thadguidry@gmail.com>
 Theo Belaire <theo.belaire@gmail.com>
@@ -1092,8 +1239,11 @@ Till Hoeppner <till@hoeppner.ws>
 Tim Brooks <brooks@cern.ch>
 Tim Chevalier <chevalier@alum.wellesley.edu>
 Tim Cuthbertson <tim@gfxmonk.net>
+Tim Dumol <tim@timdumol.com>
+Tim JIANG <p90eri@gmail.com>
 Tim Joseph Dumol <tim@timdumol.com>
 Tim Kuehn <tkuehn@cmu.edu>
+Tim Neumann <mail@timnn.me>
 Timon Rapp <timon@zaeda.net>
 Timothée Ravier <tim@siosm.fr>
 Tim Parenti <timparenti@gmail.com>
@@ -1131,6 +1281,7 @@ tynopex <tynopex@users.noreply.github.com>
 Ty Overby <ty@pre-alpha.com>
 Ulrik Sverdrup <bluss@users.noreply.github.com>
 Ulysse Carion <ulysse@ulysse.io>
+U-NOV2010\eugals <bogus>
 User Jyyou <jyyou@plaslab.cs.nctu.edu.tw>
 Utkarsh Kukreti <utkarshkukreti@gmail.com>
 Uwe Dauernheim <uwe@dauernheim.net>
@@ -1138,6 +1289,7 @@ Vadim Chugunov <vadimcn@gmail.com>
 Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
 Valentin Tsatskin <vtsatskin@mozilla.com>
 Valerii Hiora <valerii.hiora@gmail.com>
+Viacheslav Chimishuk <Viacheslav.Chemishuk@keystonett.com>
 Victor Berger <victor.berger@m4x.org>
 Victor van den Elzen <victor.vde@gmail.com>
 Victory <git@dfhu.org>
@@ -1157,6 +1309,7 @@ Vladimir Rutsky <rutsky@users.noreply.github.com>
 Vladimir Smola <smola.vladimir@gmail.com>
 Vojtech Kral <vojtech@kral.hk>
 Volker Mische <volker.mische@gmail.com>
+w00ns <w00ns@w00ns.top>
 Wade Mealing <wmealing@gmail.com>
 Wangshan Lu <wisagan@gmail.com>
 WebeWizard <webewizard@gmail.com>
@@ -1173,10 +1326,16 @@ Will Hipschman <whipsch@gmail.com>
 William Throwe <wtt6@cornell.edu>
 William Ting <io@williamting.com>
 Willson Mock <willson.mock@gmail.com>
+Will Speak <lithiumflame@gmail.com>
 Will <will@glozer.net>
+Willy Aguirre <marti1125@gmail.com>
+Without Boats <woboats@gmail.com>
 Wojciech Ogrodowczyk <github@haikuco.de>
 wonyong kim <wonyong.kim@samsung.com>
 xales <xales@naveria.com>
+Xavier Shay <xavier@rhnh.net>
+xd1le <elisp.vim@gmail.com>
+Xiao Chuan Yu <xcyu.se@gmail.com>
 Xuefeng Wu <benewu@gmail.com>
 XuefengWu <benewu@gmail.com>
 Xuefeng Wu <xfwu@thoughtworks.com>
@@ -1187,6 +1346,7 @@ Yazhong Liu <yorkiefixer@gmail.com>
 Yehuda Katz <wycats@gmail.com>
 Yongqian Li <yongqli@kerrmetric.com>
 York Xiang <bombless@126.com>
+Yoshito Komatsu <ykomatsu@akaumigame.org>
 Young-il Choi <duddlf.choi@samsung.com>
 Youngmin Yoo <youngmin.yoo@samsung.com>
 Youngsoo Son <ysson83@gmail.com>
index f81bb0bd69dd8feb2786b59a03831ec10cc63fda..515e6e18f705035649d61a2caf10f37ebe225f25 100644 (file)
@@ -145,10 +145,15 @@ To save @bors some work, and to get small changes through more quickly, when
 the other rollup-eligible patches too, and they'll get tested and merged at
 the same time.
 
-To find documentation-related issues, sort by the [A-docs label][adocs]. 
+To find documentation-related issues, sort by the [A-docs label][adocs].
 
 [adocs]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AA-docs
 
+In many cases, you don't need a full `make doc`. You can use `rustdoc` directly
+to check small fixes. For example, `rustdoc src/doc/reference.md` will render
+reference to `doc/reference.html`. The CSS might be messed up, but you can
+verify that HTML is right.
+
 ## Issue Triage
 
 Sometimes, an issue will stay open, even though the bug has been fixed. And
@@ -164,30 +169,30 @@ Contributors with sufficient permissions on the Rust repo can help by adding
 labels to triage issues:
 
 * Yellow, **A**-prefixed labels state which **area** of the project an issue
-  relates to. 
+  relates to.
 
-* Magenta, **B**-prefixed labels identify bugs which **belong** elsewhere. 
+* Magenta, **B**-prefixed labels identify bugs which **belong** elsewhere.
 
 * Green, **E**-prefixed labels explain the level of **experience** necessary
   to fix the issue.
 
 * Red, **I**-prefixed labels indicate the **importance** of the issue. The
   [I-nominated][inom] label indicates that an issue has been nominated for
-  prioritizing at the next triage meeting. 
+  prioritizing at the next triage meeting.
 
 * Orange, **P**-prefixed labels indicate a bug's **priority**. These labels
   are only assigned during triage meetings, and replace the [I-nominated][inom]
-  label. 
+  label.
 
 * Blue, **T**-prefixed bugs denote which **team** the issue belongs to.
 
 * Dark blue, **beta-** labels track changes which need to be backported into
-  the beta branches. 
+  the beta branches.
+
 * The purple **metabug** label marks lists of bugs collected by other
-  categories.  
+  categories.
 
-If you're looking for somewhere to start, check out the [E-easy][eeasy] tag. 
+If you're looking for somewhere to start, check out the [E-easy][eeasy] tag.
 
 [inom]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AI-nominated
 [eeasy]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy
@@ -221,18 +226,19 @@ are:
 * The [Rust Internals forum][rif], a place to ask questions and
   discuss Rust's internals
 * The [generated documentation for rust's compiler][gdfrustc]
-* The [rust referance][rr], even though it doesn't specifically talk about Rust's internals, its a great reasource nontheless
+* The [rust reference][rr], even though it doesn't specifically talk about Rust's internals, it's a great resource nonetheless
 * Although out of date, [Tom Lee's great blog article][tlgba] is very helpful
 * [rustaceans.org][ro] is helpful, but mostly dedicated to IRC
 * The [Rust Compiler Testing Docs][rctd]
-* For @bors, [this cheetsheat][cheetsheat] is helpful (Remember to replace `@homu` with `@bors` in the commands that you use.)
-* **Google**!
+* For @bors, [this cheat sheet][cheatsheet] is helpful (Remember to replace `@homu` with `@bors` in the commands that you use.)
+* **Google!** ([search only in Rust Documentation][gsearchdocs] to find types, traits, etc. quickly)
 * Don't be afraid to ask! The Rust community is friendly and helpful.
 
 [gdfrustc]: http://manishearth.github.io/rust-internals-docs/rustc/
+[gsearchdocs]: https://www.google.de/search?q=site:doc.rust-lang.org+your+query+here
 [rif]: http://internals.rust-lang.org
 [rr]: https://doc.rust-lang.org/book/README.html
 [tlgba]: http://tomlee.co/2014/04/03/a-more-detailed-tour-of-the-rust-compiler/
 [ro]: http://www.rustaceans.org/
 [rctd]: ./COMPILER_TESTS.md
-[cheetsheat]: http://buildbot.rust-lang.org/homu/
+[cheatsheet]: http://buildbot.rust-lang.org/homu/
index 8968fabf1b4b37f54bcc03c6e34b75ac1980ed49..baa7e77394a0da49f690c804860af26e528771e7 100644 (file)
@@ -26,7 +26,7 @@
 #
 #   * check - Run the complete test suite
 #
-#   * clean - Clean the build repertory. It is advised to run this
+#   * clean - Clean the build repository. It is advised to run this
 #             command if you want to build Rust again, after an update
 #             of the git repository.
 #
index 67285da2e3a6518294d898bd6fc4eab7d310f7a3..acd9cb6afc8d7e03ed452e5bc418b3e64fe50aef 100644 (file)
--- a/README.md
+++ b/README.md
@@ -67,11 +67,14 @@ Read ["Installing Rust"] from [The Book].
    ```sh
    # Update package mirrors (may be needed if you have a fresh install of MSYS2)
    $ pacman -Sy pacman-mirrors
-   
+
    # Choose one based on platform:
    $ pacman -S mingw-w64-i686-toolchain
    $ pacman -S mingw-w64-x86_64-toolchain
 
+   # Make git available in MSYS2 (if not already available on path)
+   $ pacman -S git
+
    $ pacman -S base-devel
    ```
 
@@ -84,6 +87,13 @@ Read ["Installing Rust"] from [The Book].
    $ ./configure
    $ make && make install
    ```
+> ***Note:*** gcc versions >= 5 currently have issues building LLVM on Windows
+> resulting in a segmentation fault when building Rust. In order to avoid this
+> it may be necessary to obtain an earlier version of gcc such as 4.9.x.
+> Installers for earlier Windows builds of gcc are available at the
+> [Mingw-Builds] project. For more information on this see issue #28260.
+
+[Mingw-Builds]: http://sourceforge.net/projects/mingw-w64/
 
 ## Building Documentation
 
@@ -98,7 +108,7 @@ Building the documentation requires building the compiler, so the above
 details will apply. Once you have the compiler built, you can
 
 ```sh
-$ make docs NO_REBUILD=1 
+$ make docs NO_REBUILD=1
 ```
 
 To make sure you don’t re-build the compiler because you made a change
index 76246640ca7bb43d2dd00900272a8a9bf7f8331f..f8679431339daea3c3369d14682508fc8578e23e 100644 (file)
@@ -1,5 +1,223 @@
-Version 1.4.0 (October 2015)
-============================
+Version 1.5.0 (2015-12-10)
+==========================
+
+* ~700 changes, numerous bugfixes
+
+Highlights
+----------
+
+* Stabilized APIs:
+  [`BinaryHeap::from`], [`BinaryHeap::into_sorted_vec`],
+  [`BinaryHeap::into_vec`], [`Condvar::wait_timeout`],
+  [`FileTypeExt::is_block_device`], [`FileTypeExt::is_char_device`],
+  [`FileTypeExt::is_fifo`], [`FileTypeExt::is_socket`],
+  [`FileTypeExt`], [`Formatter::alternate`], [`Formatter::fill`],
+  [`Formatter::precision`], [`Formatter::sign_aware_zero_pad`],
+  [`Formatter::sign_minus`], [`Formatter::sign_plus`],
+  [`Formatter::width`], [`Iterator::cmp`], [`Iterator::eq`],
+  [`Iterator::ge`], [`Iterator::gt`], [`Iterator::le`],
+  [`Iterator::lt`], [`Iterator::ne`], [`Iterator::partial_cmp`],
+  [`Path::canonicalize`], [`Path::exists`], [`Path::is_dir`],
+  [`Path::is_file`], [`Path::metadata`], [`Path::read_dir`],
+  [`Path::read_link`], [`Path::symlink_metadata`],
+  [`Utf8Error::valid_up_to`], [`Vec::resize`],
+  [`VecDeque::as_mut_slices`], [`VecDeque::as_slices`],
+  [`VecDeque::insert`], [`VecDeque::shrink_to_fit`],
+  [`VecDeque::swap_remove_back`], [`VecDeque::swap_remove_front`],
+  [`slice::split_first_mut`], [`slice::split_first`],
+  [`slice::split_last_mut`], [`slice::split_last`],
+  [`char::from_u32_unchecked`], [`fs::canonicalize`],
+  [`str::MatchIndices`], [`str::RMatchIndices`],
+  [`str::match_indices`], [`str::rmatch_indices`],
+  [`str::slice_mut_unchecked`], [`string::ParseError`].
+* Rust applications hosted on crates.io can be installed locally to
+  `~/.cargo/bin` with the [`cargo install`] command. Among other
+  things this makes it easier to augment Cargo with new subcommands:
+  when a binary named e.g. `cargo-foo` is found in `$PATH` it can be
+  invoked as `cargo foo`.
+* Crates with wildcard (`*`) dependencies will [emit warnings when
+  published][1.5w]. In 1.6 it will no longer be possible to publish
+  crates with wildcard dependencies.
+
+Breaking Changes
+----------------
+
+* The rules determining when a particular lifetime must outlive
+  a particular value (known as '[dropck]') have been [modified
+  to not rely on parametricity][1.5p].
+* [Implementations of `AsRef` and `AsMut` were added to `Box`, `Rc`,
+  and `Arc`][1.5a]. Because these smart pointer types implement
+  `Deref`, this causes breakage in cases where the interior type
+  contains methods of the same name.
+* [Correct a bug in Rc/Arc][1.5c] that caused [dropck] to be unaware
+  that they could drop their content. Soundness fix.
+* All method invocations are [properly checked][1.5wf1] for
+  [well-formedness][1.5wf2]. Soundness fix.
+* Traits whose supertraits contain `Self` are [not object
+  safe][1.5o]. Soundness fix.
+* Target specifications support a [`no_default_libraries`][1.5nd]
+  setting that controls whether `-nodefaultlibs` is passed to the
+  linker, and in turn the `is_like_windows` setting no longer affects
+  the `-nodefaultlibs` flag.
+* `#[derive(Show)]`, long-deprecated, [has been removed][1.5ds].
+* The `#[inline]` and `#[repr]` attributes [can only appear
+  in valid locations][1.5at].
+* Native libraries linked from the local crate are [passed to
+  the linker before native libraries from upstream crates][1.5nl].
+* Two rarely-used attributes, `#[no_debug]` and
+  `#[omit_gdb_pretty_printer_section]` [are feature gated][1.5fg].
+* Negation of unsigned integers, which has been a warning for
+  several releases, [is now behind a feature gate and will
+  generate errors][1.5nu].
+* The parser accidentally accepted visibility modifiers on
+  enum variants, a bug [which has been fixed][1.5ev].
+* [A bug was fixed that allowed `use` statements to import unstable
+  features][1.5use].
+
+Language
+--------
+
+* When evaluating expressions at compile-time that are not
+  compile-time constants (const-evaluating expressions in non-const
+  contexts), incorrect code such as overlong bitshifts and arithmetic
+  overflow will [generate a warning instead of an error][1.5ce],
+  delaying the error until runtime. This will allow the
+  const-evaluator to be expanded in the future backwards-compatibly.
+* The `improper_ctypes` lint [no longer warns about using `isize` and
+  `usize` in FFI][1.5ict].
+
+Libraries
+---------
+
+* `Arc<T>` and `Rc<T>` are [covariant with respect to `T` instead of
+  invariant][1.5c].
+* `Default` is [implemented for mutable slices][1.5d].
+* `FromStr` is [implemented for `SockAddrV4` and `SockAddrV6`][1.5s].
+* There are now `From` conversions [between floating point
+  types][1.5f] where the conversions are lossless.
+* Thera are now `From` conversions [between integer types][1.5i] where
+  the conversions are lossless.
+* [`fs::Metadata` implements `Clone`][1.5fs].
+* The `parse` method [accepts a leading "+" when parsing
+  integers][1.5pi].
+* [`AsMut` is implemented for `Vec`][1.5am].
+* The `clone_from` implementations for `String` and `BinaryHeap` [have
+  been optimized][1.5cf] and no longer rely on the default impl.
+* The `extern "Rust"`, `extern "C"`, `unsafe extern "Rust"` and
+  `unsafe extern "C"` function types now [implement `Clone`,
+  `PartialEq`, `Eq`, `PartialOrd`, `Ord`, `Hash`, `fmt::Pointer`, and
+  `fmt::Debug` for up to 12 arguments][1.5fp].
+* [Dropping `Vec`s is much faster in unoptimized builds when the
+  element types don't implement `Drop`][1.5dv].
+* A bug that caused in incorrect behavior when [combining `VecDeque`
+  with zero-sized types][1.5vdz] was resolved.
+* [`PartialOrd` for slices is faster][1.5po].
+
+Miscellaneous
+-------------
+
+* [Crate metadata size was reduced by 20%][1.5md].
+* [Improvements to code generation reduced the size of libcore by 3.3
+  MB and rustc's memory usage by 18MB][1.5m].
+* [Improvements to deref translation increased performance in
+  unoptimized builds][1.5dr].
+* Various errors in trait resolution [are deduplicated to only be
+  reported once][1.5te].
+* Rust has preliminary [support for rumprun kernels][1.5rr].
+* Rust has preliminary [support for NetBSD on amd64][1.5na].
+
+[1.5use]: https://github.com/rust-lang/rust/pull/28364
+[1.5po]: https://github.com/rust-lang/rust/pull/28436
+[1.5ev]: https://github.com/rust-lang/rust/pull/28442
+[1.5nu]: https://github.com/rust-lang/rust/pull/28468
+[1.5dr]: https://github.com/rust-lang/rust/pull/28491
+[1.5vdz]: https://github.com/rust-lang/rust/pull/28494
+[1.5md]: https://github.com/rust-lang/rust/pull/28521
+[1.5fg]: https://github.com/rust-lang/rust/pull/28522
+[1.5dv]: https://github.com/rust-lang/rust/pull/28531
+[1.5na]: https://github.com/rust-lang/rust/pull/28543
+[1.5fp]: https://github.com/rust-lang/rust/pull/28560
+[1.5rr]: https://github.com/rust-lang/rust/pull/28593
+[1.5cf]: https://github.com/rust-lang/rust/pull/28602
+[1.5nl]: https://github.com/rust-lang/rust/pull/28605
+[1.5te]: https://github.com/rust-lang/rust/pull/28645
+[1.5at]: https://github.com/rust-lang/rust/pull/28650
+[1.5am]: https://github.com/rust-lang/rust/pull/28663
+[1.5m]: https://github.com/rust-lang/rust/pull/28778
+[1.5ict]: https://github.com/rust-lang/rust/pull/28779
+[1.5a]: https://github.com/rust-lang/rust/pull/28811
+[1.5pi]: https://github.com/rust-lang/rust/pull/28826
+[1.5ce]: https://github.com/rust-lang/rfcs/blob/master/text/1229-compile-time-asserts.md
+[1.5p]: https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
+[1.5i]: https://github.com/rust-lang/rust/pull/28921
+[1.5fs]: https://github.com/rust-lang/rust/pull/29021
+[1.5f]: https://github.com/rust-lang/rust/pull/29129
+[1.5ds]: https://github.com/rust-lang/rust/pull/29148
+[1.5s]: https://github.com/rust-lang/rust/pull/29190
+[1.5d]: https://github.com/rust-lang/rust/pull/29245
+[1.5o]: https://github.com/rust-lang/rust/pull/29259
+[1.5nd]: https://github.com/rust-lang/rust/pull/28578
+[1.5wf2]: https://github.com/rust-lang/rfcs/blob/master/text/1214-projections-lifetimes-and-wf.md
+[1.5wf1]: https://github.com/rust-lang/rust/pull/28669
+[dropck]: https://doc.rust-lang.org/nightly/nomicon/dropck.html
+[1.5c]: https://github.com/rust-lang/rust/pull/29110
+[1.5w]: https://github.com/rust-lang/rfcs/blob/master/text/1241-no-wildcard-deps.md
+[`cargo install`]: https://github.com/rust-lang/rfcs/blob/master/text/1200-cargo-install.md
+[`BinaryHeap::from`]: http://doc.rust-lang.org/nightly/std/convert/trait.From.html#method.from
+[`BinaryHeap::into_sorted_vec`]: http://doc.rust-lang.org/nightly/std/collections/struct.BinaryHeap.html#method.into_sorted_vec
+[`BinaryHeap::into_vec`]: http://doc.rust-lang.org/nightly/std/collections/struct.BinaryHeap.html#method.into_vec
+[`Condvar::wait_timeout`]: http://doc.rust-lang.org/nightly/std/sync/struct.Condvar.html#method.wait_timeout
+[`FileTypeExt::is_block_device`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_block_device
+[`FileTypeExt::is_char_device`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_char_device
+[`FileTypeExt::is_fifo`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_fifo
+[`FileTypeExt::is_socket`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_socket
+[`FileTypeExt`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html
+[`Formatter::alternate`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.alternate
+[`Formatter::fill`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.fill
+[`Formatter::precision`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.precision
+[`Formatter::sign_aware_zero_pad`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.sign_aware_zero_pad
+[`Formatter::sign_minus`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.sign_minus
+[`Formatter::sign_plus`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.sign_plus
+[`Formatter::width`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.width
+[`Iterator::cmp`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.cmp
+[`Iterator::eq`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.eq
+[`Iterator::ge`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.ge
+[`Iterator::gt`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.gt
+[`Iterator::le`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.le
+[`Iterator::lt`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.lt
+[`Iterator::ne`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.ne
+[`Iterator::partial_cmp`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.partial_cmp
+[`Path::canonicalize`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.canonicalize
+[`Path::exists`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.exists
+[`Path::is_dir`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.is_dir
+[`Path::is_file`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.is_file
+[`Path::metadata`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.metadata
+[`Path::read_dir`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.read_dir
+[`Path::read_link`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.read_link
+[`Path::symlink_metadata`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.symlink_metadata
+[`Utf8Error::valid_up_to`]: http://doc.rust-lang.org/nightly/core/str/struct.Utf8Error.html#method.valid_up_to
+[`Vec::resize`]: http://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.resize
+[`VecDeque::as_mut_slices`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.as_mut_slices
+[`VecDeque::as_slices`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.as_slices
+[`VecDeque::insert`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.insert
+[`VecDeque::shrink_to_fit`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.shrink_to_fit
+[`VecDeque::swap_remove_back`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.swap_remove_back
+[`VecDeque::swap_remove_front`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.swap_remove_front
+[`slice::split_first_mut`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_first_mut
+[`slice::split_first`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_first
+[`slice::split_last_mut`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_last_mut
+[`slice::split_last`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_last
+[`char::from_u32_unchecked`]: http://doc.rust-lang.org/nightly/std/char/fn.from_u32_unchecked.html
+[`fs::canonicalize`]: http://doc.rust-lang.org/nightly/std/fs/fn.canonicalize.html
+[`str::MatchIndices`]: http://doc.rust-lang.org/nightly/std/str/struct.MatchIndices.html
+[`str::RMatchIndices`]: http://doc.rust-lang.org/nightly/std/str/struct.RMatchIndices.html
+[`str::match_indices`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.match_indices
+[`str::rmatch_indices`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.rmatch_indices
+[`str::slice_mut_unchecked`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.slice_mut_unchecked
+[`string::ParseError`]: http://doc.rust-lang.org/nightly/std/string/enum.ParseError.html
+
+Version 1.4.0 (2015-10-29)
+==========================
 
 * ~1200 changes, numerous bugfixes
 
@@ -20,6 +238,12 @@ Breaking Changes
 * [The `str::lines` and `BufRead::lines` iterators treat `\r\n` as
   line breaks in addition to `\n`][crlf].
 * [Loans of `'static` lifetime extend to the end of a function][stat].
+* [`str::parse` no longer introduces avoidable rounding error when
+  parsing floating point numbers. Together with earlier changes to
+  float formatting/output, "round trips" like f.to_string().parse()
+  now preserve the value of f exactly. Additionally, leading plus
+  signs are now accepted][fp3].
+
 
 Language
 --------
@@ -68,19 +292,22 @@ Libraries
   prelude][pr].
 * [`Extend<String>` and `FromIterator<String` are both implemented for
   `String`][es].
-* [`IntoIterator` is implemented for `Option<&T>` and
-  `Result<&T>`][into].
+* [`IntoIterator` is implemented for references to `Option` and
+  `Result`][into2].
 * [`HashMap` and `HashSet` implement `Extend<&T>` where `T:
-  Copy`][ext] as part of [RFC 839].
+  Copy`][ext] as part of [RFC 839]. This will cause type inferance
+  breakage in rare situations.
 * [`BinaryHeap` implements `Debug`][bh2].
 * [`Borrow` and `BorrowMut` are implemented for fixed-size
   arrays][bm].
-* [`extern fn`s of with the "Rust" and "C" ABIs implement common
+* [`extern fn`s with the "Rust" and "C" ABIs implement common
   traits including `Eq`, `Ord`, `Debug`, `Hash`][fp].
 * [String comparison is faster][faststr].
-* `&mut T` where `T: Write` [also implements `Write`][mutw].
-* [A stable regression in `VecDec::push_back` that caused panics for
-  zero-sized types was fixed][vd].
+* `&mut T` where `T: std::fmt::Write` [also implements
+  `std::fmt::Write`][mutw].
+* [A stable regression in `VecDeque::push_back` and other
+  capicity-altering methods that caused panics for zero-sized types
+  was fixed][vd].
 * [Function pointers implement traits for up to 12 parameters][fp2].
 
 Miscellaneous
@@ -151,8 +378,9 @@ Miscellaneous
 [ffi]: https://github.com/rust-lang/rust/pull/28779
 [fp]: https://github.com/rust-lang/rust/pull/28268
 [fp2]: https://github.com/rust-lang/rust/pull/28560
+[fp3]: https://github.com/rust-lang/rust/pull/27307
 [i]: https://github.com/rust-lang/rust/pull/27451
-[into]: https://github.com/rust-lang/rust/pull/28039
+[into2]: https://github.com/rust-lang/rust/pull/28039
 [it]: https://github.com/rust-lang/rust/pull/27652
 [mm]: https://github.com/rust-lang/rust/pull/27338
 [mutw]: https://github.com/rust-lang/rust/pull/28368
@@ -802,7 +1030,7 @@ Misc
 [path-normalize]: https://github.com/rust-lang/rust/pull/23229
 
 
-Version 1.0.0-alpha.2 (February 2015)
+Version 1.0.0-alpha.2 (2015-02-20)
 =====================================
 
 * ~1300 changes, numerous bugfixes
@@ -901,7 +1129,7 @@ Version 1.0.0-alpha.2 (February 2015)
 [un]: https://github.com/rust-lang/rust/pull/22256
 
 
-Version 1.0.0-alpha (January 2015)
+Version 1.0.0-alpha (2015-01-09)
 ==================================
 
   * ~2400 changes, numerous bugfixes
@@ -1088,7 +1316,7 @@ Version 1.0.0-alpha (January 2015)
 [rbe]: http://rustbyexample.com/
 
 
-Version 0.12.0 (October 2014)
+Version 0.12.0 (2014-10-09)
 =============================
 
   * ~1900 changes, numerous bugfixes
@@ -1211,7 +1439,7 @@ Version 0.12.0 (October 2014)
       kernels and distributions, built on CentOS 5.10.
 
 
-Version 0.11.0 (July 2014)
+Version 0.11.0 (2014-07-02)
 ==========================
 
   * ~1700 changes, numerous bugfixes
@@ -1344,7 +1572,7 @@ Version 0.11.0 (July 2014)
       greatly improved.
 
 
-Version 0.10 (April 2014)
+Version 0.10 (2014-04-03)
 =========================
 
   * ~1500 changes, numerous bugfixes
@@ -1511,7 +1739,7 @@ Version 0.10 (April 2014)
         directory.
 
 
-Version 0.9 (January 2014)
+Version 0.9 (2014-01-09)
 ==========================
 
    * ~1800 changes, numerous bugfixes
@@ -1677,7 +1905,7 @@ Version 0.9 (January 2014)
         build tools.
 
 
-Version 0.8 (September 2013)
+Version 0.8 (2013-09-26)
 ============================
 
    * ~2200 changes, numerous bugfixes
@@ -1833,7 +2061,7 @@ Version 0.8 (September 2013)
         still invoked through the normal `rustdoc` command.
 
 
-Version 0.7 (July 2013)
+Version 0.7 (2013-07-03)
 =======================
 
    * ~2000 changes, numerous bugfixes
@@ -1950,7 +2178,7 @@ Version 0.7 (July 2013)
       * Improvements to rustpkg (see the detailed release notes).
 
 
-Version 0.6 (April 2013)
+Version 0.6 (2013-04-03)
 ========================
 
    * ~2100 changes, numerous bugfixes
@@ -2053,7 +2281,7 @@ Version 0.6 (April 2013)
       * Inline assembler supported by new asm!() syntax extension.
 
 
-Version 0.5 (December 2012)
+Version 0.5 (2012-12-21)
 ===========================
 
    * ~900 changes, numerous bugfixes
@@ -2110,7 +2338,7 @@ Version 0.5 (December 2012)
       * License changed from MIT to dual MIT/APL2
 
 
-Version 0.4 (October 2012)
+Version 0.4 (2012-10-15)
 ==========================
 
    * ~2000 changes, numerous bugfixes
@@ -2166,7 +2394,7 @@ Version 0.4 (October 2012)
       * All hash functions and tables converted to secure, randomized SipHash
 
 
-Version 0.3  (July 2012)
+Version 0.3  (2012-07-12)
 ========================
 
    * ~1900 changes, numerous bugfixes
@@ -2225,7 +2453,7 @@ Version 0.3  (July 2012)
       * Cargo automatically resolves dependencies
 
 
-Version 0.2  (March 2012)
+Version 0.2  (2012-03-29)
 =========================
 
    * >1500 changes, numerous bugfixes
@@ -2266,7 +2494,7 @@ Version 0.2  (March 2012)
       * Extensive cleanup, regularization in libstd, libcore
 
 
-Version 0.1  (January 20, 2012)
+Version 0.1  (2012-01-20)
 ===============================
 
    * Most language features work, including:
index 2d03b5f6f41ea600acde37e627b232bc3d2f92ed..60d366100f8c207b38132e07cbebac40dcb9bdb4 100755 (executable)
--- a/configure
+++ b/configure
@@ -578,6 +578,7 @@ 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 llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM"
 opt rpath 0 "build rpaths into rustc itself"
+opt stage0-landing-pads 1 "enable landing pads during bootstrap with stage0"
 # This is used by the automation to produce single-target nightlies
 opt dist-host-only 0 "only install bins for the host architecture"
 opt inject-std-version 1 "inject the current compiler version of libstd into programs"
@@ -766,8 +767,6 @@ probe CFG_ANTLR4           antlr4
 probe CFG_GRUN             grun
 probe CFG_FLEX             flex
 probe CFG_BISON            bison
-probe CFG_PANDOC           pandoc
-probe CFG_XELATEX          xelatex
 probe CFG_GDB              gdb
 probe CFG_LLDB             lldb
 
@@ -826,26 +825,6 @@ step_msg "looking for target specific programs"
 
 probe CFG_ADB        adb
 
-if [ -n "$CFG_PANDOC" ]
-then
-    # Extract "MAJOR MINOR" from Pandoc's version number
-    PV_MAJOR_MINOR=$(pandoc --version | grep '^pandoc' |
-        sed -E 's/pandoc(.exe)? ([0-9]+)\.([0-9]+).*/\2 \3/')
-
-    MIN_PV_MAJOR="1"
-    MIN_PV_MINOR="9"
-
-    # these patterns are shell globs, *not* regexps
-    PV_MAJOR=${PV_MAJOR_MINOR% *}
-    PV_MINOR=${PV_MAJOR_MINOR#* }
-
-    if [ "$PV_MAJOR" -lt "$MIN_PV_MAJOR" ] || [ "$PV_MINOR" -lt "$MIN_PV_MINOR" ]
-    then
-        step_msg "pandoc $PV_MAJOR.$PV_MINOR is too old. Need at least $MIN_PV_MAJOR.$MIN_PV_MINOR. Disabling"
-        BAD_PANDOC=1
-    fi
-fi
-
 BIN_SUF=
 if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] || [ "$CFG_OSTYPE" = "pc-windows-msvc" ]
 then
@@ -1095,6 +1074,12 @@ envopt CPP
 envopt CFLAGS
 envopt CXXFLAGS
 
+# stdc++ name in use
+# used to manage non-standard name (on OpenBSD for example)
+program_transform_name=$($CFG_CC -v 2>&1 | sed -n "s/.*--program-transform-name='\([^']*\)'.*/\1/p")
+CFG_STDCPP_NAME=$(echo "stdc++" | sed "${program_transform_name}")
+putvar CFG_STDCPP_NAME
+
 # a little post-processing of various config values
 CFG_PREFIX=${CFG_PREFIX%/}
 CFG_MANDIR=${CFG_MANDIR%/}
@@ -1289,6 +1274,12 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
             putvar CFG_MSVC_LIB_PATH_${bits}
             ;;
 
+        *-rumprun-netbsd)
+            step_msg "targeting rumprun-netbsd, disabling jemalloc"
+            CFG_DISABLE_JEMALLOC=1
+            putvar CFG_DISABLE_JEMALLOC
+            ;;
+
         *)
             ;;
     esac
@@ -1763,12 +1754,6 @@ then
 fi
 
 
-if [ -n $BAD_PANDOC ]
-then
-    CFG_PANDOC=
-    putvar CFG_PANDOC
-fi
-
 putvar CFG_LLVM_SRC_DIR
 
 for t in $CFG_HOST
index 3ac79ecae64e5b4feaa298c0df7f54ac2cfd9aa6..56e3fe0515eb9b7dbe34dc8fed719acb39686347 100644 (file)
@@ -53,7 +53,9 @@ Comma separated list of types of crates for the compiler to emit.
 Specify the name of the crate being built.
 .TP
 \fB\-\-emit\fR [asm|llvm\-bc|llvm\-ir|obj|link|dep\-info]
-Configure the output that \fBrustc\fR will produce.
+Configure the output that \fBrustc\fR will produce. Each option may also be of
+the form KIND=PATH to specify the explicit output location for that particular
+emission kind.
 .TP
 \fB\-\-print\fR [crate\-name|file\-names|sysroot]
 Comma separated list of compiler information to print on stdout.
@@ -66,7 +68,8 @@ Equivalent to \fI\-C\ opt\-level=2\fR.
 .TP
 \fB\-o\fR \fIFILENAME\fR
 Write output to \fIFILENAME\fR.
-Ignored if multiple \fI\-\-emit\fR outputs are specified.
+Ignored if multiple \fI\-\-emit\fR outputs are specified which don't have an
+explicit path otherwise.
 .TP
 \fB\-\-out\-dir\fR \fIDIR\fR
 Write output to compiler\[hy]chosen filename in \fIDIR\fR.
index ba5f6d0e756343af7fb01c1b2e398d9644f56018..65b08774d49a01977ebadb02fd1de6b602f73edd 100644 (file)
@@ -7,8 +7,8 @@ CFG_LIB_NAME_mips-unknown-linux-gnu=lib$(1).so
 CFG_STATIC_LIB_NAME_mips-unknown-linux-gnu=lib$(1).a
 CFG_LIB_GLOB_mips-unknown-linux-gnu=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_mips-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
-CFG_JEMALLOC_CFLAGS_mips-unknown-linux-gnu := -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS)
-CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS)
+CFG_JEMALLOC_CFLAGS_mips-unknown-linux-gnu := -mips32r2 -msoft-float -mabi=32 $(CFLAGS)
+CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -msoft-float -mabi=32 $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_mips-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_mips-unknown-linux-gnu := -shared -fPIC -g -mips32r2 -msoft-float -mabi=32
 CFG_GCCISH_DEF_FLAG_mips-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
@@ -20,5 +20,5 @@ CFG_UNIXY_mips-unknown-linux-gnu := 1
 CFG_LDPATH_mips-unknown-linux-gnu :=
 CFG_RUN_mips-unknown-linux-gnu=
 CFG_RUN_TARG_mips-unknown-linux-gnu=
-RUSTC_FLAGS_mips-unknown-linux-gnu := -C target-cpu=mips32r2 -C target-feature="+mips32r2,+o32" -C soft-float
+RUSTC_FLAGS_mips-unknown-linux-gnu := -C target-cpu=mips32r2 -C target-feature="+mips32r2" -C soft-float
 CFG_GNU_TRIPLE_mips-unknown-linux-gnu := mips-unknown-linux-gnu
index 539038c7434606dfc4825052af1a35a431445096..4dadfc275d3c5a518021e059ce0570c399f0c2ea 100644 (file)
@@ -1,8 +1,8 @@
 # mipsel-unknown-linux-gnu configuration
-CC_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-gcc
-CXX_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-g++
-CPP_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-gcc
-AR_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-ar
+CC_mipsel-unknown-linux-gnu=mipsel-linux-gnu-gcc
+CXX_mipsel-unknown-linux-gnu=mipsel-linux-gnu-g++
+CPP_mipsel-unknown-linux-gnu=mipsel-linux-gnu-gcc
+AR_mipsel-unknown-linux-gnu=mipsel-linux-gnu-ar
 CFG_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).so
 CFG_STATIC_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).a
 CFG_LIB_GLOB_mipsel-unknown-linux-gnu=lib$(1)-*.so
@@ -20,5 +20,5 @@ CFG_UNIXY_mipsel-unknown-linux-gnu := 1
 CFG_LDPATH_mipsel-unknown-linux-gnu :=
 CFG_RUN_mipsel-unknown-linux-gnu=
 CFG_RUN_TARG_mipsel-unknown-linux-gnu=
-RUSTC_FLAGS_mipsel-unknown-linux-gnu := -C target-cpu=mips32 -C target-feature="+mips32,+o32"
+RUSTC_FLAGS_mipsel-unknown-linux-gnu := -C target-cpu=mips32 -C target-feature="+mips32"
 CFG_GNU_TRIPLE_mipsel-unknown-linux-gnu := mipsel-unknown-linux-gnu
diff --git a/mk/cfg/x86_64-rumprun-netbsd.mk b/mk/cfg/x86_64-rumprun-netbsd.mk
new file mode 100644 (file)
index 0000000..5894805
--- /dev/null
@@ -0,0 +1,24 @@
+# x86_64-rumprun-netbsd configuration
+CROSS_PREFIX_x86_64-rumprun-netbsd=x86_64-rumprun-netbsd-
+CC_x86_64-rumprun-netbsd=gcc
+CXX_x86_64-rumprun-netbsd=g++
+CPP_x86_64-rumprun-netbsd=gcc -E
+AR_x86_64-rumprun-netbsd=ar
+CFG_INSTALL_ONLY_RLIB_x86_64-rumprun-netbsd = 1
+CFG_LIB_NAME_x86_64-rumprun-netbsd=lib$(1).so
+CFG_STATIC_LIB_NAME_x86_64-rumprun-netbsd=lib$(1).a
+CFG_LIB_GLOB_x86_64-rumprun-netbsd=lib$(1)-*.so
+CFG_JEMALLOC_CFLAGS_x86_64-rumprun-netbsd := -m64
+CFG_GCCISH_CFLAGS_x86_64-rumprun-netbsd := -Wall -Werror -g -fPIC -m64
+CFG_GCCISH_CXXFLAGS_x86_64-rumprun-netbsd :=
+CFG_GCCISH_LINK_FLAGS_x86_64-rumprun-netbsd :=
+CFG_GCCISH_DEF_FLAG_x86_64-rumprun-netbsd :=
+CFG_LLC_FLAGS_x86_64-rumprun-netbsd :=
+CFG_INSTALL_NAME_x86_64-rumprun-netbsd =
+CFG_EXE_SUFFIX_x86_64-rumprun-netbsd =
+CFG_WINDOWSY_x86_64-rumprun-netbsd :=
+CFG_UNIXY_x86_64-rumprun-netbsd := 1
+CFG_LDPATH_x86_64-rumprun-netbsd :=
+CFG_RUN_x86_64-rumprun-netbsd=$(2)
+CFG_RUN_TARG_x86_64-rumprun-netbsd=$(call CFG_RUN_x86_64-rumprun-netbsd,,$(2))
+CFG_GNU_TRIPLE_x86_64-rumprun-netbsd := x86_64-rumprun-netbsd
index 401b0fb7ab0082084a524bc93d515747b0dd9abf..a77c5fa542eb187535d205e2132082ccbcb46e66 100644 (file)
@@ -1,4 +1,5 @@
 # x86_64-unknown-netbsd configuration
+CROSS_PREFIX_x86_64-unknown-netbsd=x86_64-unknown-netbsd-
 CC_x86_64-unknown-netbsd=$(CC)
 CXX_x86_64-unknown-netbsd=$(CXX)
 CPP_x86_64-unknown-netbsd=$(CPP)
index b424c1d8779934861f5a11f1c9947a37bf419909..6673b9b28e7163a3c71e0fdd41dec83bd224a08d 100644 (file)
@@ -61,51 +61,55 @@ HOST_CRATES := syntax $(RUSTC_CRATES) rustdoc fmt_macros
 TOOLS := compiletest rustdoc rustc rustbook error-index-generator
 
 DEPS_core :=
+DEPS_alloc := core libc alloc_system
+DEPS_alloc_system := core libc
+DEPS_collections := core alloc rustc_unicode
 DEPS_libc := core
+DEPS_rand := core
+DEPS_rustc_bitflags := core
 DEPS_rustc_unicode := core
-DEPS_alloc := core libc alloc_system
+
 DEPS_std := core libc rand alloc collections rustc_unicode \
        native:rust_builtin native:backtrace \
        alloc_system
+DEPS_arena := std
+DEPS_glob := std
+DEPS_flate := std native:miniz
+DEPS_fmt_macros = std
+DEPS_getopts := std
 DEPS_graphviz := std
+DEPS_log := std
+DEPS_num := std
+DEPS_rbml := std log serialize
+DEPS_serialize := std log
+DEPS_term := std log
+DEPS_test := std getopts serialize rbml term native:rust_test_helpers
+
 DEPS_syntax := std term serialize log fmt_macros arena libc rustc_bitflags
+
+DEPS_rustc := syntax flate arena serialize getopts rbml rustc_front\
+              log graphviz rustc_llvm rustc_back rustc_data_structures
+DEPS_rustc_back := std syntax rustc_llvm rustc_front flate log libc
+DEPS_rustc_borrowck := rustc rustc_front log graphviz syntax
+DEPS_rustc_data_structures := std log serialize
 DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \
                      rustc_typeck rustc_mir rustc_resolve log syntax serialize rustc_llvm \
                             rustc_trans rustc_privacy rustc_lint rustc_front
 
-DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
-                       log syntax serialize rustc_llvm rustc_front rustc_platform_intrinsics
-DEPS_rustc_mir := rustc rustc_front syntax
-DEPS_rustc_typeck := rustc syntax rustc_front rustc_platform_intrinsics
-DEPS_rustc_borrowck := rustc rustc_front log graphviz syntax
-DEPS_rustc_resolve := rustc rustc_front log syntax
-DEPS_rustc_privacy := rustc rustc_front log syntax
+DEPS_rustc_front := std syntax log serialize
 DEPS_rustc_lint := rustc log syntax
-DEPS_rustc := syntax flate arena serialize getopts rbml \
-              log graphviz rustc_llvm rustc_back rustc_data_structures
 DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
+DEPS_rustc_mir := rustc rustc_front syntax
+DEPS_rustc_resolve := rustc rustc_front log syntax
 DEPS_rustc_platform_intrinsics := rustc rustc_llvm
-DEPS_rustc_back := std syntax rustc_llvm rustc_front flate log libc
-DEPS_rustc_front := std syntax log serialize
-DEPS_rustc_data_structures := std log serialize
+DEPS_rustc_privacy := rustc rustc_front log syntax
+DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
+                    log syntax serialize rustc_llvm rustc_front rustc_platform_intrinsics
+DEPS_rustc_typeck := rustc syntax rustc_front rustc_platform_intrinsics
+
 DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \
                 test rustc_lint rustc_front
-DEPS_rustc_bitflags := core
-DEPS_flate := std native:miniz
-DEPS_arena := std
-DEPS_graphviz := std
-DEPS_glob := std
-DEPS_serialize := std log
-DEPS_rbml := std log serialize
-DEPS_term := std log
-DEPS_getopts := std
-DEPS_collections := core alloc rustc_unicode
-DEPS_num := std
-DEPS_test := std getopts serialize rbml term native:rust_test_helpers
-DEPS_rand := core
-DEPS_log := std
-DEPS_fmt_macros = std
-DEPS_alloc_system := core libc
+
 
 TOOL_DEPS_compiletest := test getopts
 TOOL_DEPS_rustdoc := rustdoc
index 0fc9100b85b92873aae0269ed816d3c9c1d595a8..4cdee8bda9d4c2d1afe990e8e4314f6e3dc28caf 100644 (file)
@@ -21,6 +21,7 @@
 # * dist-docs - Stage docs for upload
 
 PKG_NAME := $(CFG_PACKAGE_NAME)
+STD_PKG_NAME := rust-std-$(CFG_PACKAGE_VERS)
 DOC_PKG_NAME := rust-docs-$(CFG_PACKAGE_VERS)
 MINGW_PKG_NAME := rust-mingw-$(CFG_PACKAGE_VERS)
 
@@ -77,6 +78,7 @@ $(PKG_TAR): $(PKG_FILES)
          -C $(S) \
          --exclude-vcs \
          --exclude=*~ \
+         --exclude=*.pyc \
          --exclude=*/llvm/test/*/*.ll \
          --exclude=*/llvm/test/*/*.td \
          --exclude=*/llvm/test/*/*.s \
@@ -111,19 +113,25 @@ distcheck-tar-src: dist-tar-src
 # Unix binary installer tarballs
 ######################################################################
 
-define DEF_INSTALLER
+define DEF_START_INSTALLER
+dist-install-dir-$(1)-%: PREPARE_DIR_CMD=$(DEFAULT_PREPARE_DIR_CMD)
+dist-install-dir-$(1)-%: PREPARE_BIN_CMD=$(DEFAULT_PREPARE_BIN_CMD)
+dist-install-dir-$(1)-%: PREPARE_LIB_CMD=$(DEFAULT_PREPARE_LIB_CMD)
+dist-install-dir-$(1)-%: PREPARE_MAN_CMD=$(DEFAULT_PREPARE_MAN_CMD)
+dist-install-dir-$(1)-%: PREPARE_CLEAN=true
 
 $$(eval $$(call DEF_PREPARE,dir-$(1)))
+endef
 
-dist-install-dir-$(1): PREPARE_HOST=$(1)
-dist-install-dir-$(1): PREPARE_TARGETS=$(2)
-dist-install-dir-$(1): PREPARE_DEST_DIR=tmp/dist/$$(PKG_NAME)-$(1)-image
-dist-install-dir-$(1): PREPARE_DIR_CMD=$(DEFAULT_PREPARE_DIR_CMD)
-dist-install-dir-$(1): PREPARE_BIN_CMD=$(DEFAULT_PREPARE_BIN_CMD)
-dist-install-dir-$(1): PREPARE_LIB_CMD=$(DEFAULT_PREPARE_LIB_CMD)
-dist-install-dir-$(1): PREPARE_MAN_CMD=$(DEFAULT_PREPARE_MAN_CMD)
-dist-install-dir-$(1): PREPARE_CLEAN=true
-dist-install-dir-$(1): prepare-base-dir-$(1) docs
+$(foreach target,$(CFG_TARGET),\
+  $(eval $(call DEF_START_INSTALLER,$(target))))
+
+define DEF_INSTALLER
+
+dist-install-dir-$(1)-host: PREPARE_HOST=$(1)
+dist-install-dir-$(1)-host: PREPARE_TARGETS=$(2)
+dist-install-dir-$(1)-host: PREPARE_DEST_DIR=tmp/dist/$$(PKG_NAME)-$(1)-image
+dist-install-dir-$(1)-host: prepare-base-dir-$(1)-host docs
        $$(Q)mkdir -p $$(PREPARE_DEST_DIR)/share/doc/rust
        $$(Q)$$(PREPARE_MAN_CMD) $$(S)COPYRIGHT $$(PREPARE_DEST_DIR)/share/doc/rust
        $$(Q)$$(PREPARE_MAN_CMD) $$(S)LICENSE-APACHE $$(PREPARE_DEST_DIR)/share/doc/rust
@@ -140,14 +148,27 @@ prepare-overlay-$(1):
 # This tiny morsel of metadata is used by rust-packaging
        $$(Q)echo "$(CFG_VERSION)" > tmp/dist/$$(PKG_NAME)-$(1)-overlay/version
 
-dist/$$(PKG_NAME)-$(1).tar.gz: dist-install-dir-$(1) prepare-overlay-$(1)
+dist/$$(PKG_NAME)-$(1).tar.gz: dist-install-dir-$(1)-host prepare-overlay-$(1)
        @$(call E, build: $$@)
-# Copy essential gcc components into installer
-ifdef CFG_WINDOWSY_$(1)
-ifeq ($$(findstring gnu,$(1)),gnu)
+# On a MinGW target we've got a few runtime DLL dependencies that we need
+# to include. THe first argument to `make-win-dist` is where to put these DLLs
+# (the image we're creating) and the second argument is a junk directory to
+# ignore all the other MinGW stuff the script creates.
+ifeq ($$(findstring pc-windows-gnu,$(1)),pc-windows-gnu)
        $$(Q)rm -Rf tmp/dist/win-rust-gcc-$(1)
-       $$(Q)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py tmp/dist/$$(PKG_NAME)-$(1)-image tmp/dist/win-rust-gcc-$(1) $(1)
-       $$(Q)cp -r $$(S)src/etc/third-party tmp/dist/$$(PKG_NAME)-$(1)-image/share/doc/
+       $$(Q)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py \
+               tmp/dist/$$(PKG_NAME)-$(1)-image \
+               tmp/dist/win-rust-gcc-$(1) $(1)
+endif
+# On 32-bit MinGW we're always including a DLL which needs some extra licenses
+# to distribute. On 64-bit MinGW we don't actually distribute anything requiring
+# us to distribute a license but it's likely that the install will *also*
+# include the rust-mingw package down below, which also need licenses, so to be
+# safe we just inlude it here in all MinGW packages.
+ifdef CFG_WINDOWSY_$(1)
+ifeq ($$(findstring $(1),gnu),gnu)
+       $$(Q)cp -r $$(S)src/etc/third-party \
+               tmp/dist/$$(PKG_NAME)-$(1)-image/share/doc/
 endif
 endif
        $$(Q)$$(S)src/rust-installer/gen-installer.sh \
@@ -182,11 +203,16 @@ dist/$$(DOC_PKG_NAME)-$(1).tar.gz: dist-doc-install-dir-$(1)
                --bulk-dirs=share/doc/rust/html
        $$(Q)rm -R tmp/dist/$$(DOC_PKG_NAME)-$(1)-image
 
+# Creates the rust-mingw package, and the first argument to make-win-dist is a
+# "temporary directory" which is just thrown away (this contains the runtime
+# DLLs included in the rustc package above) and the second argument is where to
+# place all the MinGW components (which is what we want).
 dist-mingw-install-dir-$(1):
        $$(Q)mkdir -p tmp/dist/rust-mingw-tmp-$(1)-image
        $$(Q)rm -Rf tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image
        $$(Q)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py \
-               tmp/dist/rust-mingw-tmp-$(1)-image tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image $(1)
+               tmp/dist/rust-mingw-tmp-$(1)-image \
+               tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image $(1)
 
 dist/$$(MINGW_PKG_NAME)-$(1).tar.gz: dist-mingw-install-dir-$(1)
        @$(call E, build: $$@)
@@ -204,15 +230,52 @@ dist/$$(MINGW_PKG_NAME)-$(1).tar.gz: dist-mingw-install-dir-$(1)
 
 endef
 
-ifneq ($(CFG_ENABLE_DIST_HOST_ONLY),)
-$(foreach host,$(CFG_HOST),\
-  $(eval $(call DEF_INSTALLER,$(host),$(host))))
-else
+# $(1) - host
+# $(2) - target
+define DEF_INSTALLER_TARGETS
+
+dist-install-dir-$(2)-target: PREPARE_HOST=$(1)
+dist-install-dir-$(2)-target: PREPARE_TARGETS=$(2)
+dist-install-dir-$(2)-target: PREPARE_DEST_DIR=tmp/dist/$$(STD_PKG_NAME)-$(2)-image
+dist-install-dir-$(2)-target: prepare-base-dir-$(2)-target
+
+dist/$$(STD_PKG_NAME)-$(2).tar.gz: dist-install-dir-$(2)-target
+       @$$(call E, build: $$@)
+       $$(Q)$$(S)src/rust-installer/gen-installer.sh \
+               --product-name=Rust \
+               --rel-manifest-dir=rustlib \
+               --success-message=std-is-standing-at-the-ready. \
+               --image-dir=tmp/dist/$$(STD_PKG_NAME)-$(2)-image \
+               --work-dir=tmp/dist \
+               --output-dir=dist \
+               --package-name=$$(STD_PKG_NAME)-$(2) \
+               --component-name=rust-std-$(2) \
+               --legacy-manifest-dirs=rustlib,cargo
+       $$(Q)rm -R tmp/dist/$$(STD_PKG_NAME)-$(2)-image
+endef
+
 $(foreach host,$(CFG_HOST),\
-  $(eval $(call DEF_INSTALLER,$(host),$(CFG_TARGET))))
-endif
+  $(eval $(call DEF_INSTALLER,$(host))))
 
-dist-install-dirs: $(foreach host,$(CFG_HOST),dist-install-dir-$(host))
+# When generating packages for the standard library, we've actually got a lot of
+# artifacts to choose from. Each of the CFG_HOST compilers will have a copy of
+# the standard library for each CFG_TARGET, but we only want to generate one
+# standard library package. As a result, for each entry in CFG_TARGET we need to
+# pick a CFG_HOST to get the standard library from.
+#
+# In theory it doesn't actually matter what host we choose as it should be the
+# case that all hosts produce the same set of libraries for a target (regardless
+# of the host itself). Currently there is a bug in the compiler, however, which
+# means this is not the case (see #29228 and #29235). To solve the first of
+# those bugs, we prefer to select a standard library from the host it was
+# generated from, allowing plugins to work in more situations.
+#
+# For all CFG_TARGET entries in CFG_HOST, however, we just pick CFG_BUILD as the
+# host we slurp up a standard library from.
+$(foreach host,$(CFG_HOST),\
+  $(eval $(call DEF_INSTALLER_TARGETS,$(host),$(host))))
+$(foreach target,$(filter-out $(CFG_HOST),$(CFG_TARGET)),\
+  $(eval $(call DEF_INSTALLER_TARGETS,$(CFG_BUILD),$(target))))
 
 ifdef CFG_WINDOWSY_$(CFG_BUILD)
 define BUILD_MINGW_TARBALL
@@ -229,7 +292,9 @@ ifeq ($(CFG_DISABLE_DOCS),)
 MAYBE_DOC_TARBALLS=$(foreach host,$(CFG_HOST),dist/$(DOC_PKG_NAME)-$(host).tar.gz)
 endif
 
-dist-tar-bins: $(foreach host,$(CFG_HOST),dist/$(PKG_NAME)-$(host).tar.gz) \
+dist-tar-bins: \
+       $(foreach host,$(CFG_HOST),dist/$(PKG_NAME)-$(host).tar.gz) \
+       $(foreach target,$(CFG_TARGET),dist/$(STD_PKG_NAME)-$(target).tar.gz) \
        $(MAYBE_DOC_TARBALLS) $(MAYBE_MINGW_TARBALLS)
 
 # Just try to run the compiler for the build host
index d9c66e282bc4e22cfbeefae78bc2c267a5479bcc..0d527bd0688600bc0beb367c7ef65880171a3146 100644 (file)
@@ -58,17 +58,17 @@ check-lexer: $(BG) $(BG)RustLexer.class check-build-lexer-verifier
        $(Q)$(SG)check.sh $(S) "$(BG)" \
                "$(CFG_GRUN)" "$(BG)verify" "$(BG)RustLexer.tokens"
 else
-$(info cfg: grun not available, skipping lexer test...)
+$(info cfg: lexer tooling not available, skipping lexer test...)
 check-lexer:
 
 endif
 else
-$(info cfg: antlr4 not available, skipping lexer test...)
+$(info cfg: lexer tooling not available, skipping lexer test...)
 check-lexer:
 
 endif
 else
-$(info cfg: javac not available, skipping lexer test...)
+$(info cfg: lexer tooling not available, skipping lexer test...)
 check-lexer:
 
 endif
index cabc97a1e49120073c6e415d7546905f12e2be1b..8b8170220c9168a8db08ddf6884272cdf4346d14 100644 (file)
@@ -8,6 +8,12 @@
 # option. This file may not be copied, modified, or distributed
 # except according to those terms.
 
+RUN_INSALLER = cd tmp/empty_dir && \
+       sh ../../tmp/dist/$(1)/install.sh \
+               --prefix="$(DESTDIR)$(CFG_PREFIX)" \
+               --libdir="$(DESTDIR)$(CFG_LIBDIR)" \
+               --mandir="$(DESTDIR)$(CFG_MANDIR)"
+
 install:
 ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER)))
 # Build the dist as the original user
@@ -16,9 +22,11 @@ else
        $(Q)$(MAKE) prepare_install
 endif
 ifeq ($(CFG_DISABLE_DOCS),)
-       $(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(DOC_PKG_NAME)-$(CFG_BUILD)/install.sh --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
+       $(Q)$(call RUN_INSALLER,$(DOC_PKG_NAME)-$(CFG_BUILD)) --disable-ldconfig
 endif
-       $(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(PKG_NAME)-$(CFG_BUILD)/install.sh --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
+       $(Q)$(foreach target,$(CFG_TARGET),\
+         ($(call RUN_INSALLER,$(STD_PKG_NAME)-$(target)) --disable-ldconfig);)
+       $(Q)$(call RUN_INSALLER,$(PKG_NAME)-$(CFG_BUILD))
 # Remove tmp files because it's a decent amount of disk space
        $(Q)rm -R tmp/dist
 
@@ -32,9 +40,11 @@ else
        $(Q)$(MAKE) prepare_uninstall
 endif
 ifeq ($(CFG_DISABLE_DOCS),)
-       $(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(DOC_PKG_NAME)-$(CFG_BUILD)/install.sh --uninstall --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
+       $(Q)$(call RUN_INSALLER,$(DOC_PKG_NAME)-$(CFG_BUILD)) --uninstall
 endif
-       $(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(PKG_NAME)-$(CFG_BUILD)/install.sh --uninstall --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
+       $(Q)$(call RUN_INSALLER,$(PKG_NAME)-$(CFG_BUILD)) --uninstall
+       $(Q)$(foreach target,$(CFG_TARGET),\
+         ($(call RUN_INSALLER,$(STD_PKG_NAME)-$(target)) --uninstall);)
 # Remove tmp files because it's a decent amount of disk space
        $(Q)rm -R tmp/dist
 
index d5b608e88daf85852291ca4ced7c14ec4f45513e..1cbf4a9fb841c26db01d99472f25fe9fd931f938 100644 (file)
@@ -73,7 +73,7 @@ $$(LLVM_STAMP_$(1)): $(S)src/rustllvm/llvm-auto-clean-trigger
 
 ifeq ($$(CFG_ENABLE_LLVM_STATIC_STDCPP),1)
 LLVM_STDCPP_RUSTFLAGS_$(1) = -L "$$(dir $$(shell $$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \
-                                       -print-file-name=libstdc++.a))"
+                                       -print-file-name=lib$(CFG_STDCPP_NAME).a))"
 else
 LLVM_STDCPP_RUSTFLAGS_$(1) =
 endif
@@ -83,7 +83,7 @@ endif
 LLVM_LINKAGE_PATH_$(1):=$$(abspath $$(RT_OUTPUT_DIR_$(1))/llvmdeps.rs)
 $$(LLVM_LINKAGE_PATH_$(1)): $(S)src/etc/mklldeps.py $$(LLVM_CONFIG_$(1))
        $(Q)$(CFG_PYTHON) "$$<" "$$@" "$$(LLVM_COMPONENTS)" "$$(CFG_ENABLE_LLVM_STATIC_STDCPP)" \
-               $$(LLVM_CONFIG_$(1))
+               $$(LLVM_CONFIG_$(1)) "$(CFG_STDCPP_NAME)"
 endef
 
 $(foreach host,$(CFG_HOST), \
index f13355517d868c60812e434a8f81675f50d1f2a0..34f82479662fc399e50f5a583e84a4ebd0b776b5 100644 (file)
 ######################################################################
 
 # The version number
-CFG_RELEASE_NUM=1.4.0
+CFG_RELEASE_NUM=1.5.0
 
 # An optional number to put after the label, e.g. '.2' -> '-beta.2'
 # NB Make sure it starts with a dot to conform to semver pre-release
 # versions (section 9)
-CFG_PRERELEASE_VERSION=.4
+CFG_PRERELEASE_VERSION=.5
 
 # Append a version-dependent hash to each library, so we can install different
 # versions in the same place
@@ -132,7 +132,11 @@ endif
 
 ifdef CFG_ENABLE_DEBUGINFO
   $(info cfg: enabling debuginfo (CFG_ENABLE_DEBUGINFO))
-  CFG_RUSTC_FLAGS += -g
+  # FIXME: Re-enable -g in stage0 after new snapshot
+  #CFG_RUSTC_FLAGS += -g
+  RUSTFLAGS_STAGE1 += -g
+  RUSTFLAGS_STAGE2 += -g
+  RUSTFLAGS_STAGE3 += -g
 endif
 
 ifdef SAVE_TEMPS
@@ -170,19 +174,10 @@ RUST_LIB_FLAGS_ST3 += -C prefer-dynamic
 
 # Landing pads require a lot of codegen. We can get through bootstrapping faster
 # by not emitting them.
-RUSTFLAGS_STAGE0 += -Z no-landing-pads
-
-# Enable MIR to "always build" for crates where this works. This is
-# just temporary while MIR is being actively built up -- it's just a
-# poor man's unit testing infrastructure. Anyway we only want this for
-# stage1/stage2.
-define ADD_MIR_FLAG
-RUSTFLAGS1_$(1) += -Z always-build-mir
-RUSTFLAGS2_$(1) += -Z always-build-mir
-endef
-$(foreach crate,$(TARGET_CRATES),$(eval $(call ADD_MIR_FLAG,$(crate))))
-$(foreach crate,$(RUSTC_CRATES),$(eval $(call ADD_MIR_FLAG,$(crate))))
-$(foreach crate,$(HOST_CRATES),$(eval $(call ADD_MIR_FLAG,$(crate))))
+
+ifdef CFG_DISABLE_STAGE0_LANDING_PADS
+  RUSTFLAGS_STAGE0 += -Z no-landing-pads
+endif
 
 # platform-specific auto-configuration
 include $(CFG_SRC_DIR)mk/platform.mk
index fcb6a5b50d3cebc049cca98288e20035460dc08e..856a22dc6067d503507d7641e521e521983ca45f 100644 (file)
@@ -208,6 +208,14 @@ define CFG_MAKE_TOOLCHAIN
 
   ifeq ($$(findstring $(HOST_$(1)),arm aarch64 mips mipsel powerpc),)
 
+  # On OpenBSD, we need to pass the path of libstdc++.so to the linker
+  # (use path of libstdc++.a which is a known name for the same path)
+  ifeq ($(OSTYPE_$(1)),unknown-openbsd)
+    RUSTC_FLAGS_$(1)=-L "$$(dir $$(shell $$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \
+        -print-file-name=lib$(CFG_STDCPP_NAME).a))" \
+        $(RUSTC_FLAGS_$(1))
+  endif
+
   # On Bitrig, we need the relocation model to be PIC for everything
   ifeq (,$(filter $(OSTYPE_$(1)),bitrig))
     LLVM_MC_RELOCATION_MODEL="pic"
index fe619cc7caec76f3d8f4dfcda82a0621c21efee3..e263a6d2e4d32ab6c13c9d8484cfa3fa9c8295a6 100644 (file)
@@ -185,16 +185,16 @@ INSTALL_DEBUGGER_SCRIPT_COMMANDS=$(if $(findstring windows,$(1)),\
 
 define DEF_PREPARE
 
-prepare-base-$(1): PREPARE_SOURCE_DIR=$$(PREPARE_HOST)/stage$$(PREPARE_STAGE)
-prepare-base-$(1): PREPARE_SOURCE_BIN_DIR=$$(PREPARE_SOURCE_DIR)/bin
-prepare-base-$(1): PREPARE_SOURCE_LIB_DIR=$$(PREPARE_SOURCE_DIR)/$$(CFG_LIBDIR_RELATIVE)
-prepare-base-$(1): PREPARE_SOURCE_MAN_DIR=$$(S)/man
-prepare-base-$(1): PREPARE_DEST_BIN_DIR=$$(PREPARE_DEST_DIR)/bin
-prepare-base-$(1): PREPARE_DEST_LIB_DIR=$$(PREPARE_DEST_DIR)/$$(CFG_LIBDIR_RELATIVE)
-prepare-base-$(1): PREPARE_DEST_MAN_DIR=$$(PREPARE_DEST_DIR)/share/man/man1
-prepare-base-$(1): prepare-everything-$(1)
+prepare-base-$(1)-%: PREPARE_SOURCE_DIR=$$(PREPARE_HOST)/stage$$(PREPARE_STAGE)
+prepare-base-$(1)-%: PREPARE_SOURCE_BIN_DIR=$$(PREPARE_SOURCE_DIR)/bin
+prepare-base-$(1)-%: PREPARE_SOURCE_LIB_DIR=$$(PREPARE_SOURCE_DIR)/$$(CFG_LIBDIR_RELATIVE)
+prepare-base-$(1)-%: PREPARE_SOURCE_MAN_DIR=$$(S)/man
+prepare-base-$(1)-%: PREPARE_DEST_BIN_DIR=$$(PREPARE_DEST_DIR)/bin
+prepare-base-$(1)-%: PREPARE_DEST_LIB_DIR=$$(PREPARE_DEST_DIR)/$$(CFG_LIBDIR_RELATIVE)
+prepare-base-$(1)-%: PREPARE_DEST_MAN_DIR=$$(PREPARE_DEST_DIR)/share/man/man1
 
-prepare-everything-$(1): prepare-host-$(1) prepare-targets-$(1) prepare-debugger-scripts-$(1)
+prepare-base-$(1)-target: prepare-target-$(1)
+prepare-base-$(1)-host: prepare-host-$(1) prepare-debugger-scripts-$(1)
 
 prepare-host-$(1): prepare-host-tools-$(1)
 
@@ -222,7 +222,7 @@ $$(foreach lib,$$(CRATES), \
   $$(foreach host,$$(CFG_HOST), \
     $$(eval $$(call DEF_PREPARE_HOST_LIB,$$(lib),$$(PREPARE_STAGE),$$(host),$(1)))))
 
-prepare-targets-$(1): \
+prepare-target-$(1): \
         $$(foreach host,$$(CFG_HOST), \
            $$(foreach target,$$(CFG_TARGET), \
              prepare-target-$$(target)-host-$$(host)-$$(PREPARE_STAGE)-$(1)))
index e0984cfe86f077084f49b5c011df10d4c311afd1..d004558d1bf3f58f11aab507552ca36c921ea7c7 100644 (file)
@@ -1046,6 +1046,10 @@ $$(call TEST_OK_FILE,$(1),$(2),$(3),rmake): \
                $$(RMAKE_TESTS:%=$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok)
        @touch $$@
 
+$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
+       export INCLUDE := $$(CFG_MSVC_INCLUDE_PATH_$$(HOST_$(3)))
+$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
+       export LIB := $$(CFG_MSVC_LIB_PATH_$$(HOST_$(3)))
 $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
                $(S)src/test/run-make/%/Makefile \
                $$(CSREQ$(1)_T_$(2)_H_$(3))
@@ -1056,7 +1060,7 @@ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
         $$(MAKE) \
            $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \
            $(3)/test/run-make/$$* \
-           $$(CC_$(3)) \
+           '$$(CC_$(3))' \
            "$$(CFG_GCCISH_CFLAGS_$(3))" \
            $$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
            "$$(TESTNAME)" \
@@ -1064,7 +1068,8 @@ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
            "$$(LD_LIBRARY_PATH_ENV_HOSTDIR$(1)_T_$(2)_H_$(3))" \
            "$$(LD_LIBRARY_PATH_ENV_TARGETDIR$(1)_T_$(2)_H_$(3))" \
            $(1) \
-           $$(S)
+           $$(S) \
+           $(3)
        @touch -r $$@.start_time $$@ && rm $$@.start_time
 else
 # FIXME #11094 - The above rule doesn't work right for multiple targets
index f508798a8b6ed0297a74f60d1903340651931602..dfd99a9beae96cc5ac80615ea61c181f0dd79057 100644 (file)
@@ -13,9 +13,7 @@
 #![feature(box_syntax)]
 #![feature(dynamic_lib)]
 #![feature(libc)]
-#![feature(path_ext)]
 #![feature(rustc_private)]
-#![feature(slice_splits)]
 #![feature(str_char)]
 #![feature(test)]
 #![feature(vec_push_all)]
@@ -92,7 +90,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
           optflag("h", "help", "show this message"));
 
     let (argv0, args_) = args.split_first().unwrap();
-    if args[1] == "-h" || args[1] == "--help" {
+    if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
         let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
         println!("{}", getopts::usage(&message, &groups));
         println!("");
@@ -348,7 +346,7 @@ fn extract_gdb_version(full_version_line: Option<String>) -> Option<String> {
           if !full_version_line.trim().is_empty() => {
             let full_version_line = full_version_line.trim();
 
-            // used to be a regex "(^|[^0-9])([0-9]\.[0-9])([^0-9]|$)"
+            // used to be a regex "(^|[^0-9])([0-9]\.[0-9]+)"
             for (pos, c) in full_version_line.char_indices() {
                 if !c.is_digit(10) { continue }
                 if pos + 2 >= full_version_line.len() { continue }
@@ -357,11 +355,12 @@ fn extract_gdb_version(full_version_line: Option<String>) -> Option<String> {
                 if pos > 0 && full_version_line.char_at_reverse(pos).is_digit(10) {
                     continue
                 }
-                if pos + 3 < full_version_line.len() &&
-                   full_version_line.char_at(pos + 3).is_digit(10) {
-                    continue
+                let mut end = pos + 3;
+                while end < full_version_line.len() &&
+                      full_version_line.char_at(end).is_digit(10) {
+                    end += 1;
                 }
-                return Some(full_version_line[pos..pos+3].to_owned());
+                return Some(full_version_line[pos..end].to_owned());
             }
             println!("Could not extract GDB version from line '{}'",
                      full_version_line);
index 66fa0dfecd4220d75617f98c000fa223f860786e..7c5397a1af989d474c2cd4994d1e57ce61b2af84 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(deprecated)]
+
 use std::dynamic_lib::DynamicLibrary;
 use std::io::prelude::*;
 use std::path::PathBuf;
index 12f560be45621524cc830294de53e83536bde88a..8db6725f7a8f87a0c9811a10dd6af3e0dbc0cdc3 100644 (file)
@@ -1669,8 +1669,7 @@ fn compile_test_and_save_ir(config: &Config, props: &TestProps,
     // FIXME (#9639): This needs to handle non-utf8 paths
     let mut link_args = vec!("-L".to_owned(),
                              aux_dir.to_str().unwrap().to_owned());
-    let llvm_args = vec!("--emit=llvm-ir".to_owned(),
-                         "--crate-type=lib".to_owned());
+    let llvm_args = vec!("--emit=llvm-ir".to_owned(),);
     link_args.extend(llvm_args);
     let args = make_compile_args(config,
                                  props,
index c09f28ae4f62d5cc0dd594505f39d0e50bec19ca..0882b073ea48c32109697ec28b4d65ffae767c4a 100644 (file)
@@ -2,9 +2,10 @@
 
 ## Building
 
-To generate all the docs, just run `make docs` from the root of the repository.
-This will convert the distributed Markdown docs to HTML and generate HTML doc
-for the 'std' and 'extra' libraries.
+To generate all the docs, follow the "Building Documentation" instructions in
+the README in the root of the repository. This will convert the distributed
+Markdown docs to HTML and generate HTML doc for the books, 'std' and 'extra'
+libraries.
 
 To generate HTML documentation from one source file/crate, do something like:
 
index 8b9467589c6541da4a0b34aceaba02c9cffb69ab..05c17606ce0342f705cfe52c36dd24d7cfa075f8 100644 (file)
@@ -76,7 +76,7 @@ Cleanup through RAII-style destructors is more likely to work than in catch bloc
 
 ## Why aren't modules type-parametric?
 
-We want to maintain the option to parametrize at runtime. We may eventually change this limitation, but initially this is how type parameters were implemented.
+We want to maintain the option to parameterize at runtime. We may eventually change this limitation, but initially this is how type parameters were implemented.
 
 ## Why aren't values type-parametric? Why only items?
 
index bb1805d694fd090e6085690aeef069042dc19656..1ed961fd558674ef677bfff181b4e4594ce2751c 100644 (file)
@@ -22,7 +22,7 @@ Existing languages at this level of abstraction and efficiency are unsatisfactor
 
 # Is any part of this thing production-ready?
 
-No. Feel free to play around, but don't expect completeness or stability yet. Expect incompleteness and breakage.
+Yes!
 
 # Is this a completely Mozilla-planned and orchestrated thing?
 
index 3ae93b8f279dc6aa961e71affb60b1ce77747d72..a400e70e97dfd86ad76694e11ea8b92e6f7c09a3 100644 (file)
@@ -9,7 +9,7 @@ provides only one kind of material:
 
 This document does not serve as an introduction to the language. Background
 familiarity with the language is assumed. A separate [guide] is available to
-help acquire such background familiarity.
+help acquire such background.
 
 This document also does not serve as a reference to the [standard] library
 included in the language distribution. Those libraries are documented
@@ -258,8 +258,8 @@ symbol : "::" | "->"
        | ',' | ';' ;
 ```
 
-Symbols are a general class of printable [token](#tokens) that play structural
-roles in a variety of grammar productions. They are catalogued here for
+Symbols are a general class of printable [tokens](#tokens) that play structural
+roles in a variety of grammar productions. They are cataloged 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).
@@ -436,7 +436,7 @@ meta_seq : meta_item [ ',' meta_seq ] ? ;
 ## Statements
 
 ```antlr
-stmt : decl_stmt | expr_stmt ;
+stmt : decl_stmt | expr_stmt | ';' ;
 ```
 
 ### Declaration statements
@@ -773,7 +773,7 @@ bound := path | lifetime
 
 ## Type kinds
 
-**FIXME:** this this probably not relevant to the grammar...
+**FIXME:** this is probably not relevant to the grammar...
 
 # Memory and concurrency models
 
index 1e667d3600fb4649fe45b27ca523ba89e1fa218a..992b6eef5e80112589caad61fb93a12d6f08beda 100644 (file)
@@ -98,3 +98,4 @@ languages:
 - [Korean](https://github.com/rust-kr/doc.rust-kr.org)
 - [Chinese](https://github.com/KaiserY/rust-book-chinese)
 - [Spanish](https://goyox86.github.io/elpr)
+- [German](https://panicbit.github.io/rustbook-de)
index 08f0de4f00677d0348d8bd2966318da85cce22ef..1efca08abd094d7b6833a2e4ff47f6a41aed4b23 100644 (file)
@@ -1,11 +1,11 @@
 % Atomics
 
 Rust pretty blatantly just inherits C11's memory model for atomics. This is not
-due this model being particularly excellent or easy to understand. Indeed, this
-model is quite complex and known to have [several flaws][C11-busted]. Rather, it
-is a pragmatic concession to the fact that *everyone* is pretty bad at modeling
-atomics. At very least, we can benefit from existing tooling and research around
-C.
+due to this model being particularly excellent or easy to understand. Indeed,
+this model is quite complex and known to have [several flaws][C11-busted].
+Rather, it is a pragmatic concession to the fact that *everyone* is pretty bad
+at modeling atomics. At very least, we can benefit from existing tooling and
+research around C.
 
 Trying to fully explain the model in this book is fairly hopeless. It's defined
 in terms of madness-inducing causality graphs that require a full book to
index 5f07709cf4542efbd6a46bb3ce16eac783fd3b52..6cc41bd9533c76f6ed51157a57b57c484daa106c 100644 (file)
@@ -52,7 +52,7 @@ For numeric casts, there are quite a few cases to consider:
     * zero-extend if the source is unsigned
     * sign-extend if the source is signed
 * casting from a float to an integer will round the float towards zero
-    * **[NOTE: currently this will cause Undefined Behaviour if the rounded
+    * **[NOTE: currently this will cause Undefined Behavior if the rounded
       value cannot be represented by the target integer type][float-int]**.
       This includes Inf and NaN. This is a bug and will be fixed.
 * casting from an integer to float will produce the floating point
@@ -61,7 +61,7 @@ For numeric casts, there are quite a few cases to consider:
 * casting from an f32 to an f64 is perfect and lossless
 * casting from an f64 to an f32 will produce the closest possible value
   (rounding strategy unspecified)
-    * **[NOTE: currently this will cause Undefined Behaviour if the value
+    * **[NOTE: currently this will cause Undefined Behavior if the value
       is finite but larger or smaller than the largest or smallest finite
       value representable by f32][float-float]**. This is a bug and will
       be fixed.
index 802f3204cd4527f377153349ac025913a16f3292..b93b303f0b96e26667dfee9f2acc0dfe9f52421a 100644 (file)
@@ -1,4 +1,4 @@
-% Concurrency and Paralellism
+% Concurrency and Parallelism
 
 Rust as a language doesn't *really* have an opinion on how to do concurrency or
 parallelism. The standard library exposes OS threads and blocking sys-calls
index 91abdab9778f2fc55a9ed9a72474f95334464599..604370b636517c8216c9c7fcaf5e169758536ef2 100644 (file)
@@ -17,7 +17,7 @@ boilerplate" to drop children. If a struct has no special logic for being
 dropped other than dropping its children, then it means `Drop` doesn't need to
 be implemented at all!
 
-**There is no stable way to prevent this behaviour in Rust 1.0.**
+**There is no stable way to prevent this behavior in Rust 1.0.**
 
 Note that taking `&mut self` means that even if you could suppress recursive
 Drop, Rust will prevent you from e.g. moving fields out of self. For most types,
@@ -53,7 +53,7 @@ impl<T> Drop for Box<T> {
 
 and this works fine because when Rust goes to drop the `ptr` field it just sees
 a [Unique] that has no actual `Drop` implementation. Similarly nothing can
-use-after-free the `ptr` because when drop exits, it becomes inacessible.
+use-after-free the `ptr` because when drop exits, it becomes inaccessible.
 
 However this wouldn't work:
 
@@ -101,7 +101,7 @@ After we deallocate the `box`'s ptr in SuperBox's destructor, Rust will
 happily proceed to tell the box to Drop itself and everything will blow up with
 use-after-frees and double-frees.
 
-Note that the recursive drop behaviour applies to all structs and enums
+Note that the recursive drop behavior applies to all structs and enums
 regardless of whether they implement Drop. Therefore something like
 
 ```rust
index 5655c5d245ce0638658550e82814e7a6d2389d4b..cfceafe1bdf23ec4294224720c13bc98bece967c 100644 (file)
@@ -40,7 +40,7 @@ y = x;                   // y was init; Drop y, overwrite it, and make x uninit!
                          // x goes out of scope; x was uninit; do nothing.
 ```
 
-Similarly, branched code where all branches have the same behaviour with respect
+Similarly, branched code where all branches have the same behavior with respect
 to initialization has static drop semantics:
 
 ```rust
index 98d269ff76282a389848b76b9f1e5006753bedc9..ad7c65032c76995d03896affcc372543b2706a05 100644 (file)
@@ -6,7 +6,7 @@ interacted with the *outlives* relationship in an inclusive manner. That is,
 when we talked about `'a: 'b`, it was ok for `'a` to live *exactly* as long as
 `'b`. At first glance, this seems to be a meaningless distinction. Nothing ever
 gets dropped at the same time as another, right? This is why we used the
-following desugarring of `let` statements:
+following desugaring of `let` statements:
 
 ```rust,ignore
 let x;
@@ -115,13 +115,163 @@ section:
 **For a generic type to soundly implement drop, its generics arguments must
 strictly outlive it.**
 
-This rule is sufficient but not necessary to satisfy the drop checker. That is,
-if your type obeys this rule then it's definitely sound to drop. However
-there are special cases where you can fail to satisfy this, but still
-successfully pass the borrow checker. These are the precise rules that are
-currently up in the air.
+Obeying this rule is (usually) necessary to satisfy the borrow
+checker; obeying it is sufficient but not necessary to be
+sound. That is, if your type obeys this rule then it's definitely
+sound to drop.
+
+The reason that it is not always necessary to satisfy the above rule
+is that some Drop implementations will not access borrowed data even
+though their type gives them the capability for such access.
+
+For example, this variant of the above `Inspector` example will never
+accessed borrowed data:
+
+```rust,ignore
+struct Inspector<'a>(&'a u8, &'static str);
+
+impl<'a> Drop for Inspector<'a> {
+    fn drop(&mut self) {
+        println!("Inspector(_, {}) knows when *not* to inspect.", self.1);
+    }
+}
+
+fn main() {
+    let (inspector, days);
+    days = Box::new(1);
+    inspector = Inspector(&days, "gadget");
+    // Let's say `days` happens to get dropped first.
+    // Even when Inspector is dropped, its destructor will not access the
+    // borrowed `days`.
+}
+```
+
+Likewise, this variant will also never access borrowed data:
+
+```rust,ignore
+use std::fmt;
+
+struct Inspector<T: fmt::Display>(T, &'static str);
+
+impl<T: fmt::Display> Drop for Inspector<T> {
+    fn drop(&mut self) {
+        println!("Inspector(_, {}) knows when *not* to inspect.", self.1);
+    }
+}
+
+fn main() {
+    let (inspector, days): (Inspector<&u8>, Box<u8>);
+    days = Box::new(1);
+    inspector = Inspector(&days, "gadget");
+    // Let's say `days` happens to get dropped first.
+    // Even when Inspector is dropped, its destructor will not access the
+    // borrowed `days`.
+}
+```
+
+However, *both* of the above variants are rejected by the borrow
+checker during the analysis of `fn main`, saying that `days` does not
+live long enough.
+
+The reason is that the borrow checking analysis of `main` does not
+know about the internals of each Inspector's Drop implementation.  As
+far as the borrow checker knows while it is analyzing `main`, the body
+of an inspector's destructor might access that borrowed data.
+
+Therefore, the drop checker forces all borrowed data in a value to
+strictly outlive that value.
+
+# An Escape Hatch
+
+The precise rules that govern drop checking may be less restrictive in
+the future.
+
+The current analysis is deliberately conservative and trivial; it forces all
+borrowed data in a value to outlive that value, which is certainly sound.
+
+Future versions of the language may make the analysis more precise, to
+reduce the number of cases where sound code is rejected as unsafe.
+This would help address cases such as the two Inspectors above that
+know not to inspect during destruction.
+
+In the meantime, there is an unstable attribute that one can use to
+assert (unsafely) that a generic type's destructor is *guaranteed* to
+not access any expired data, even if its type gives it the capability
+to do so.
+
+That attribute is called `unsafe_destructor_blind_to_params`.
+To deploy it on the Inspector example from above, we would write:
+
+```rust,ignore
+struct Inspector<'a>(&'a u8, &'static str);
+
+impl<'a> Drop for Inspector<'a> {
+    #[unsafe_destructor_blind_to_params]
+    fn drop(&mut self) {
+        println!("Inspector(_, {}) knows when *not* to inspect.", self.1);
+    }
+}
+```
+
+This attribute has the word `unsafe` in it because the compiler is not
+checking the implicit assertion that no potentially expired data
+(e.g. `self.0` above) is accessed.
+
+It is sometimes obvious that no such access can occur, like the case above.
+However, when dealing with a generic type parameter, such access can
+occur indirectly. Examples of such indirect access are:
+
+ * invoking a callback,
+ * via a trait method call.
+
+(Future changes to the language, such as impl specialization, may add
+other avenues for such indirect access.)
+
+Here is an example of invoking a callback:
+
+```rust,ignore
+struct Inspector<T>(T, &'static str, Box<for <'r> fn(&'r T) -> String>);
+
+impl<T> Drop for Inspector<T> {
+    fn drop(&mut self) {
+        // The `self.2` call could access a borrow e.g. if `T` is `&'a _`.
+        println!("Inspector({}, {}) unwittingly inspects expired data.",
+                 (self.2)(&self.0), self.1);
+    }
+}
+```
+
+Here is an example of a trait method call:
+
+```rust,ignore
+use std::fmt;
+
+struct Inspector<T: fmt::Display>(T, &'static str);
+
+impl<T: fmt::Display> Drop for Inspector<T> {
+    fn drop(&mut self) {
+        // There is a hidden call to `<T as Display>::fmt` below, which
+        // could access a borrow e.g. if `T` is `&'a _`
+        println!("Inspector({}, {}) unwittingly inspects expired data.",
+                 self.0, self.1);
+    }
+}
+```
+
+And of course, all of these accesses could be further hidden within
+some other method invoked by the destructor, rather than being written
+directly within it.
+
+In all of the above cases where the `&'a u8` is accessed in the
+destructor, adding the `#[unsafe_destructor_blind_to_params]`
+attribute makes the type vulnerable to misuse that the borrower
+checker will not catch, inviting havoc. It is better to avoid adding
+the attribute.
+
+# Is that all about drop checker?
 
 It turns out that when writing unsafe code, we generally don't need to
 worry at all about doing the right thing for the drop checker. However there
 is one special case that you need to worry about, which we will look at in
 the next section.
+
index e8637e38ac7d5f7d3230a5dbca95dc854a5352f1..052e3c5fddc551ac81be5791c049ea302fff5d58 100644 (file)
@@ -20,7 +20,7 @@ information that "completes" them (more on this below).
 There are two major DSTs exposed by the language: trait objects, and slices.
 
 A trait object represents some type that implements the traits it specifies.
-The exact original type is *erased* in favour of runtime reflection
+The exact original type is *erased* in favor of runtime reflection
 with a vtable containing all the information necessary to use the type.
 This is the information that completes a trait object: a pointer to its vtable.
 
@@ -128,7 +128,7 @@ But neither of these tricks work today, so all Void types get you is
 the ability to be confident that certain situations are statically impossible.
 
 One final subtle detail about empty types is that raw pointers to them are
-actually valid to construct, but dereferencing them is Undefined Behaviour
+actually valid to construct, but dereferencing them is Undefined Behavior
 because that doesn't actually make sense. That is, you could model C's `void *`
 type with `*const Void`, but this doesn't necessarily gain anything over using
 e.g. `*const ()`, which *is* safe to randomly dereference.
index 0441db27526f870bf3d7edde3261b86bdf70a71d..a5d5742a4c62151912fae5e377def09ec5eb8530 100644 (file)
@@ -90,16 +90,16 @@ let mut vec = vec![Box::new(0); 4];
 println!("{}", vec[0]);
 ```
 
-This is pretty clearly Not Good. Unfortunately, we're kind've stuck between a
+This is pretty clearly Not Good. Unfortunately, we're kind of stuck between a
 rock and a hard place: maintaining consistent state at every step has an
 enormous cost (and would negate any benefits of the API). Failing to maintain
-consistent state gives us Undefined Behaviour in safe code (making the API
+consistent state gives us Undefined Behavior in safe code (making the API
 unsound).
 
 So what can we do? Well, we can pick a trivially consistent state: set the Vec's
 len to be 0 when we start the iteration, and fix it up if necessary in the
 destructor. That way, if everything executes like normal we get the desired
-behaviour with minimal overhead. But if someone has the *audacity* to
+behavior with minimal overhead. But if someone has the *audacity* to
 mem::forget us in the middle of the iteration, all that does is *leak even more*
 (and possibly leave the Vec in an unexpected but otherwise consistent state).
 Since we've accepted that mem::forget is safe, this is definitely safe. We call
@@ -135,7 +135,7 @@ impl<T> Rc<T> {
     fn new(data: T) -> Self {
         unsafe {
             // Wouldn't it be nice if heap::allocate worked like this?
-            let ptr = heap::allocate<RcBox<T>>();
+            let ptr = heap::allocate::<RcBox<T>>();
             ptr::write(ptr, RcBox {
                 data: data,
                 ref_count: 1,
@@ -248,4 +248,4 @@ let mut data = Box::new(0);
 ```
 
 Dang. Here the destructor running was pretty fundamental to the API, and it had
-to be scrapped in favour of a completely different design.
+to be scrapped in favor of a completely different design.
index 8b01616ee0d109efbf037b6f11dd593c42fee187..0ad8a78880e523306e293440bd40c5f8dd700991 100644 (file)
@@ -78,4 +78,4 @@ TODO: other common problems? SEME regions stuff, mostly?
 
 
 
-[ex2]: lifetimes.html#example-2:-aliasing-a-mutable-reference
+[ex2]: lifetimes.html#example-aliasing-a-mutable-reference
index 58272a1bc373b16fa952aadf6152f3615ede4603..e48d5f852f06a435cb03e81819d7d516cf8d9041 100644 (file)
@@ -195,7 +195,7 @@ println!("{}", x);
 
 The problem here is is bit more subtle and interesting. We want Rust to
 reject this program for the following reason: We have a live shared reference `x`
-to a descendent of `data` when we try to take a mutable reference to `data`
+to a descendant of `data` when we try to take a mutable reference to `data`
 to `push`. This would create an aliased mutable reference, which would
 violate the *second* rule of references.
 
index 52582e8750b4690daa82520ba8a3f3066bda496d..978d0518729ea5705e37c19834a41b6337fb0e42 100644 (file)
@@ -26,7 +26,7 @@ do some really crazy unsafe things.
 
 Safe Rust is the *true* Rust programming language. If all you do is write Safe
 Rust, you will never have to worry about type-safety or memory-safety. You will
-never endure a null or dangling pointer, or any of that Undefined Behaviour
+never endure a null or dangling pointer, or any of that Undefined Behavior
 nonsense.
 
 *That's totally awesome.*
@@ -52,11 +52,11 @@ The only things that are different in Unsafe Rust are that you can:
 * Mutate statics
 
 That's it. The reason these operations are relegated to Unsafe is that misusing
-any of these things will cause the ever dreaded Undefined Behaviour. Invoking
-Undefined Behaviour gives the compiler full rights to do arbitrarily bad things
-to your program. You definitely *should not* invoke Undefined Behaviour.
+any of these things will cause the ever dreaded Undefined Behavior. Invoking
+Undefined Behavior gives the compiler full rights to do arbitrarily bad things
+to your program. You definitely *should not* invoke Undefined Behavior.
 
-Unlike C, Undefined Behaviour is pretty limited in scope in Rust. All the core
+Unlike C, Undefined Behavior is pretty limited in scope in Rust. All the core
 language cares about is preventing the following things:
 
 * Dereferencing null or dangling pointers
@@ -71,9 +71,9 @@ language cares about is preventing the following things:
 * Unwinding into another language
 * Causing a [data race][race]
 
-That's it. That's all the causes of Undefined Behaviour baked into Rust. Of
+That's it. That's all the causes of Undefined Behavior baked into Rust. Of
 course, unsafe functions and traits are free to declare arbitrary other
-constraints that a program must maintain to avoid Undefined Behaviour. However,
+constraints that a program must maintain to avoid Undefined Behavior. However,
 generally violations of these constraints will just transitively lead to one of
 the above problems. Some additional constraints may also derive from compiler
 intrinsics that make special assumptions about how code can be optimized.
index 71da743f35d3cbc92784c5001eb0a601931cef9c..e361fbb7ae868ecaa668da896110d076b9de68e5 100644 (file)
@@ -19,8 +19,8 @@ kept in mind. Due to its dual purpose as "for FFI" and "for layout control",
 `repr(C)` can be applied to types that will be nonsensical or problematic if
 passed through the FFI boundary.
 
-* ZSTs are still zero-sized, even though this is not a standard behaviour in
-C, and is explicitly contrary to the behaviour of an empty type in C++, which
+* ZSTs are still zero-sized, even though this is not a standard behavior in
+C, and is explicitly contrary to the behavior of an empty type in C++, which
 still consumes a byte of space.
 
 * DSTs, tuples, and tagged unions are not a concept in C and as such are never
@@ -65,7 +65,7 @@ compiler might be able to paper over alignment issues with shifts and masks.
 However if you take a reference to a packed field, it's unlikely that the
 compiler will be able to emit code to avoid an unaligned load.
 
-**[As of Rust 1.0 this can cause undefined behaviour.][ub loads]**
+**[As of Rust 1.0 this can cause undefined behavior.][ub loads]**
 
 `repr(packed)` is not to be used lightly. Unless you have extreme requirements,
 this should not be used.
index e80c64c3543f8a18503d58db992b63aba2d12930..6be8d3b70286ac27b1bed67d43a85191f37218a6 100644 (file)
@@ -64,4 +64,3 @@ does in fact live as long as we needed. However it was *changed* while we had
 a reference into it. This is why Rust requires any references to freeze the
 referent and its owners.
 
-
index 3b47502ebfe790a9f6ce55454eef864bb6591fd2..f0732cf26562cf21459a5fc8bcffa574fc5d8386 100644 (file)
@@ -6,7 +6,7 @@ Safe Rust guarantees an absence of data races, which are defined as:
 * one of them is a write
 * one of them is unsynchronized
 
-A data race has Undefined Behaviour, and is therefore impossible to perform
+A data race has Undefined Behavior, and is therefore impossible to perform
 in Safe Rust. Data races are *mostly* prevented through rust's ownership system:
 it's impossible to alias a mutable reference, so it's impossible to perform a
 data race. Interior mutability makes this more complicated, which is largely why
@@ -53,7 +53,7 @@ thread::spawn(move || {
 // bounds checked, and there's no chance of the value getting changed
 // in the middle. However our program may panic if the thread we spawned
 // managed to increment before this ran. A race condition because correct
-// program execution (panicing is rarely correct) depends on order of
+// program execution (panicking is rarely correct) depends on order of
 // thread execution.
 println!("{}", data[idx.load(Ordering::SeqCst)]);
 ```
index e038ae5639bf6d3111d2a084f7dff52db0317ea4..effeaf872bbeef5dbc932e3c8ec2ea8a56a44676 100644 (file)
@@ -6,7 +6,7 @@ value of alignment `n` must only be stored at an address that is a multiple of
 `n`. So alignment 2 means you must be stored at an even address, and 1 means
 that you can be stored anywhere. Alignment is at least 1, and always a power of
 2. Most primitives are generally aligned to their size, although this is
-platform-specific behaviour. In particular, on x86 `u64` and `f64` may be only
+platform-specific behavior. In particular, on x86 `u64` and `f64` may be only
 aligned to 32 bits.
 
 A type's size must always be a multiple of its alignment. This ensures that an
@@ -151,4 +151,4 @@ use fairly elaborate algorithms to cache bits throughout nested types with
 special constrained representations. As such it is *especially* desirable that
 we leave enum layout unspecified today.
 
-[dst]: exotic-sizes.html#dynamically-sized-types-(dsts)
+[dst]: exotic-sizes.html#dynamically-sized-types-dsts
index 3cb02d31b175f5b526cefaea78c0413783fc9a5e..5fd61eb51dd1c7f6d2b7d8ed6b6af5ec70dce106 100644 (file)
@@ -41,8 +41,8 @@ Some examples of unsafe functions:
 
 * `slice::get_unchecked` will perform unchecked indexing, allowing memory
   safety to be freely violated.
-* `ptr::offset` is an intrinsic that invokes Undefined Behaviour if it is
-  not "in bounds" as defined by LLVM.
+* every raw pointer to sized type has intrinsic `offset` method that invokes
+  Undefined Behavior if it is not "in bounds" as defined by LLVM.
 * `mem::transmute` reinterprets some value as having the given type,
   bypassing type safety in arbitrary ways. (see [conversions] for details)
 * All FFI functions are `unsafe` because they can do arbitrary things.
@@ -59,9 +59,9 @@ As of Rust 1.0 there are exactly two unsafe traits:
 The need for unsafe traits boils down to the fundamental property of safe code:
 
 **No matter how completely awful Safe code is, it can't cause Undefined
-Behaviour.**
+Behavior.**
 
-This means that Unsafe Rust, **the royal vanguard of Undefined Behaviour**, has to be
+This means that Unsafe Rust, **the royal vanguard of Undefined Behavior**, has to be
 *super paranoid* about generic safe code. To be clear, Unsafe Rust is totally free to trust
 specific safe code. Anything else would degenerate into infinite spirals of
 paranoid despair. In particular it's generally regarded as ok to trust the standard library
index 9ab60d03fca7e41a6b1555f67683f207a8ed899b..134e47f18dcf0ccebf041854e4fa1af54460b1aa 100644 (file)
@@ -15,7 +15,7 @@ implement, and other unsafe code can assume that they are correctly
 implemented. Since they're *marker traits* (they have no associated items like
 methods), correctly implemented simply means that they have the intrinsic
 properties an implementor should have. Incorrectly implementing Send or Sync can
-cause Undefined Behaviour.
+cause Undefined Behavior.
 
 Send and Sync are also automatically derived traits. This means that, unlike
 every other trait, if a type is composed entirely of Send or Sync types, then it
index 2b34ad0a9fad164baf630f7bde97df6bbd1e84b1..f1478b7f668d33e67cd035d0e557d1d991a92431 100644 (file)
@@ -8,7 +8,7 @@ horribly unsafe thing you can do in Rust. The railguards here are dental floss.
 
 `mem::transmute<T, U>` takes a value of type `T` and reinterprets it to have
 type `U`. The only restriction is that the `T` and `U` are verified to have the
-same size. The ways to cause Undefined Behaviour with this are mind boggling.
+same size. The ways to cause Undefined Behavior with this are mind boggling.
 
 * First and foremost, creating an instance of *any* type with an invalid state
   is going to cause arbitrary chaos that can't really be predicted.
@@ -26,7 +26,7 @@ same size. The ways to cause Undefined Behaviour with this are mind boggling.
 `mem::transmute_copy<T, U>` somehow manages to be *even more* wildly unsafe than
 this. It copies `size_of<U>` bytes out of an `&T` and interprets them as a `U`.
 The size check that `mem::transmute` has is gone (as it may be valid to copy
-out a prefix), though it is Undefined Behaviour for `U` to be larger than `T`.
+out a prefix), though it is Undefined Behavior for `U` to be larger than `T`.
 
 Also of course you can get most of the functionality of these functions using
 pointer casts.
index b540ab4ed5d999d5c70c972fc207bd3df7c76415..2c5ba79a5078f1820daba439f613085725df0896 100644 (file)
@@ -2,7 +2,7 @@
 
 Unsafe code can often end up producing references or lifetimes out of thin air.
 Such lifetimes come into the world as *unbounded*. The most common source of this
-is derefencing a raw pointer, which produces a reference with an unbounded lifetime.
+is dereferencing a raw pointer, which produces a reference with an unbounded lifetime.
 Such a lifetime becomes as big as context demands. This is in fact more powerful
 than simply becoming `'static`, because for instance `&'static &'a T`
 will fail to typecheck, but the unbound lifetime will perfectly mold into
@@ -10,7 +10,7 @@ will fail to typecheck, but the unbound lifetime will perfectly mold into
 lifetime can be regarded as `'static`.
 
 Almost no reference is `'static`, so this is probably wrong. `transmute` and
-`transmute_copy` are the two other primary offenders. One should endeavour to
+`transmute_copy` are the two other primary offenders. One should endeavor to
 bound an unbounded lifetime as quick as possible, especially across function
 boundaries.
 
index 5ae1818dc630690de2a99a811c7c950f3c03460c..c72ed8a76329982b2582202dbf4d4d1c5b83771f 100644 (file)
@@ -38,7 +38,7 @@ dropping the old value: `write`, `copy`, and `copy_nonoverlapping`.
   (this is equivalent to memcpy -- note that the argument order is reversed!)
 
 It should go without saying that these functions, if misused, will cause serious
-havoc or just straight up Undefined Behaviour. The only things that these
+havoc or just straight up Undefined Behavior. The only things that these
 functions *themselves* require is that the locations you want to read and write
 are allocated. However the ways writing arbitrary bits to arbitrary
 locations of memory can break things are basically uncountable!
index 915ea8602918e6133e419b041f5128eb9b620b17..05615d89bec77a530522a4e227bb0ea5309d92ee 100644 (file)
@@ -4,7 +4,7 @@ All runtime-allocated memory in a Rust program begins its life as
 *uninitialized*. In this state the value of the memory is an indeterminate pile
 of bits that may or may not even reflect a valid state for the type that is
 supposed to inhabit that location of memory. Attempting to interpret this memory
-as a value of *any* type will cause Undefined Behaviour. Do Not Do This.
+as a value of *any* type will cause Undefined Behavior. Do Not Do This.
 
 Rust provides mechanisms to work with uninitialized memory in checked (safe) and
-unchecked (unsafe) ways.
\ No newline at end of file
+unchecked (unsafe) ways.
index 3ad95dde39deda47fc61395384af3915a6221097..e81f06b83b2496d61b7238a15758e4c8f240b8ce 100644 (file)
@@ -42,7 +42,7 @@ should only panic for programming errors or *extreme* problems.
 
 Rust's unwinding strategy is not specified to be fundamentally compatible
 with any other language's unwinding. As such, unwinding into Rust from another
-language, or unwinding into another language from Rust is Undefined Behaviour.
+language, or unwinding into another language from Rust is Undefined Behavior.
 You must *absolutely* catch any panics at the FFI boundary! What you do at that
 point is up to you, but *something* must be done. If you fail to do this,
 at best, your application will crash and burn. At worst, your application *won't*
index 3df63d5249c55efbe4fd3b2724e5dd208d5c3e18..7ca369da0b886be266de71952bc08704f4bb6a49 100644 (file)
@@ -93,7 +93,7 @@ pub struct Vec<T> {
 If you don't care about the null-pointer optimization, then you can use the
 stable code. However we will be designing the rest of the code around enabling
 the optimization. In particular, `Unique::new` is unsafe to call, because
-putting `null` inside of it is Undefined Behaviour. Our stable Unique doesn't
+putting `null` inside of it is Undefined Behavior. Our stable Unique doesn't
 need `new` to be unsafe because it doesn't make any interesting guarantees about
 its contents.
 
index b518e8aa48ffb1beb82b0b796cce45d60e6192f3..5e747a8c71d41bd38daf0377bbe9a41df51d0d59 100644 (file)
@@ -34,7 +34,7 @@ Easy! How about `pop`? Although this time the index we want to access is
 initialized, Rust won't just let us dereference the location of memory to move
 the value out, because that would leave the memory uninitialized! For this we
 need `ptr::read`, which just copies out the bits from the target address and
-intrprets it as a value of type T. This will leave the memory at this address
+interprets it as a value of type T. This will leave the memory at this address
 logically uninitialized, even though there is in fact a perfectly good instance
 of T there.
 
index 72e8a34488bae73751aa6306d60613d32321bbdc..fb337a891a8d42ddb50ac5ed224d931b2fee71ae 100644 (file)
@@ -1,11 +1,11 @@
 % Handling Zero-Sized Types
 
-It's time. We're going to fight the spectre that is zero-sized types. Safe Rust
+It's time. We're going to fight the specter that is zero-sized types. Safe Rust
 *never* needs to care about this, but Vec is very intensive on raw pointers and
 raw allocations, which are exactly the two things that care about
 zero-sized types. We need to be careful of two things:
 
-* The raw allocator API has undefined behaviour if you pass in 0 for an
+* The raw allocator API has undefined behavior if you pass in 0 for an
   allocation size.
 * raw pointer offsets are no-ops for zero-sized types, which will break our
   C-style pointer iterator.
index 717c99901d1bc48c4f4b2a9409d6be62eaf8094e..037fb6a8d98d88ac06cea2853740fc3a19da7ae6 100644 (file)
@@ -76,8 +76,16 @@ An identifier is any nonempty Unicode[^non_ascii_idents] string of the following
 [^non_ascii_idents]: Non-ASCII characters in identifiers are currently feature
   gated. This is expected to improve soon.
 
-- The first character has property `XID_start`
-- The remaining characters have property `XID_continue`
+Either
+
+   * The first character has property `XID_start`
+   * The remaining characters have property `XID_continue`
+
+Or
+
+   * The first character is `_`
+   * The identifier is more than one character, `_` alone is not an identifier
+   * The remaining characters have property `XID_continue`
 
 that does _not_ occur in the set of [keywords][keywords].
 
@@ -410,11 +418,14 @@ The two values of the boolean type are written `true` and `false`.
 
 ### Symbols
 
-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
+Symbols are a general class of printable [tokens](#tokens) that play structural
+roles in a variety of grammar productions. They are a
+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].
+They are catalogued in [the Symbols section][symbols] of the Grammar document.
+
+[symbols]: grammar.html#symbols
 
 
 ## Paths
@@ -586,8 +597,8 @@ Rust syntax is restricted in two ways:
 # Crates and source files
 
 Although Rust, like any other language, can be implemented by an interpreter as
-well as a compiler, the only existing implementation is a compiler &mdash;
-from now on referred to as *the* Rust compiler &mdash; and the language has
+well as a compiler, the only existing implementation is a compiler,
+and the language has
 always been designed to be compiled. For these reasons, this section assumes a
 compiler.
 
@@ -674,7 +685,7 @@ There are several kinds of item:
 * [modules](#modules)
 * [functions](#functions)
 * [type definitions](grammar.html#type-definitions)
-* [structures](#structures)
+* [structs](#structs)
 * [enumerations](#enumerations)
 * [constant items](#constant-items)
 * [static items](#static-items)
@@ -881,7 +892,7 @@ mod foo {
     }
 
     use foo::example::iter; // good: foo is at crate root
-//  use example::iter;      // bad:  core is not at the crate root
+//  use example::iter;      // bad:  example is not at the crate root
     use self::baz::foobaz;  // good: self refers to module 'foo'
     use foo::bar::foobar;   // good: foo is at crate root
 
@@ -900,9 +911,10 @@ fn main() {}
 
 ### Functions
 
-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
+A _function item_ defines a sequence of [statements](#statements) and a
+final [expression](#expressions), along with a name and a set of
+parameters. Other than a name, all these are optional.
+Functions are declared with the keyword `fn`. Functions may declare a
 set of *input* [*variables*](#variables) as parameters, through which the caller
 passes arguments into the function, and the *output* [*type*](#types)
 of the value the function will return to its caller on completion.
@@ -921,7 +933,7 @@ An example of a function:
 
 ```
 fn add(x: i32, y: i32) -> i32 {
-    return x + y;
+    x + y
 }
 ```
 
@@ -975,99 +987,6 @@ The type parameters can also be explicitly supplied in a trailing
 there is not sufficient context to determine the type parameters. For example,
 `mem::size_of::<u32>() == 4`.
 
-#### Unsafety
-
-Unsafe operations are those that potentially violate the memory-safety
-guarantees of Rust's static semantics.
-
-The following language level features cannot be used in the safe subset of
-Rust:
-
-- Dereferencing a [raw pointer](#pointer-types).
-- Reading or writing a [mutable static variable](#mutable-statics).
-- Calling an unsafe function (including an intrinsic or foreign function).
-
-##### Unsafe functions
-
-Unsafe functions are functions that are not safe in all contexts and/or for all
-possible inputs. Such a function must be prefixed with the keyword `unsafe` and
-can only be called from an `unsafe` block or another `unsafe` function.
-
-##### Unsafe blocks
-
-A block of code can be prefixed with the `unsafe` keyword, to permit calling
-`unsafe` functions or dereferencing raw pointers within a safe function.
-
-When a programmer has sufficient conviction that a sequence of potentially
-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, in the surrounding context.
-
-Unsafe blocks are used to wrap foreign libraries, make direct use of hardware
-or implement features not directly present in the language. For example, Rust
-provides the language features necessary to implement memory-safe concurrency
-in the language but the implementation of threads and message passing is in the
-standard library.
-
-Rust's type system is a conservative approximation of the dynamic safety
-requirements, so in some cases there is a performance cost to using safe code.
-For example, a doubly-linked list is not a tree structure and can only be
-represented with reference-counted pointers in safe code. By using `unsafe`
-blocks to represent the reverse links as raw pointers, it can be implemented
-with only boxes.
-
-##### Behavior considered undefined
-
-The following is a list of behavior which is forbidden in all Rust code,
-including within `unsafe` blocks and `unsafe` functions. Type checking provides
-the guarantee that these issues are never caused by safe code.
-
-* Data races
-* Dereferencing a null/dangling raw pointer
-* Reads of [undef](http://llvm.org/docs/LangRef.html#undefined-values)
-  (uninitialized) memory
-* Breaking the [pointer aliasing
-  rules](http://llvm.org/docs/LangRef.html#pointer-aliasing-rules)
-  with raw pointers (a subset of the rules used by C)
-* `&mut` and `&` follow LLVM’s scoped [noalias] model, except if the `&T`
-  contains an `UnsafeCell<U>`. Unsafe code must not violate these aliasing
-  guarantees.
-* Mutating non-mutable data (that is, data reached through a shared reference or
-  data owned by a `let` binding), unless that data is contained within an `UnsafeCell<U>`.
-* Invoking undefined behavior via compiler intrinsics:
-  * Indexing outside of the bounds of an object with `std::ptr::offset`
-    (`offset` intrinsic), with
-    the exception of one byte past the end which is permitted.
-  * Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64`
-    intrinsics) on overlapping buffers
-* Invalid values in primitive types, even in private fields/locals:
-  * Dangling/null references or boxes
-  * A value other than `false` (0) or `true` (1) in a `bool`
-  * A discriminant in an `enum` not included in the type definition
-  * A value in a `char` which is a surrogate or above `char::MAX`
-  * Non-UTF-8 byte sequences in a `str`
-* Unwinding into Rust from foreign code or unwinding from Rust into foreign
-  code. Rust's failure system is not compatible with exception handling in
-  other languages. Unwinding must be caught and handled at FFI boundaries.
-
-[noalias]: http://llvm.org/docs/LangRef.html#noalias
-
-##### Behavior not considered unsafe
-
-This is a list of behavior not considered *unsafe* in Rust terms, but that may
-be undesired.
-
-* Deadlocks
-* Leaks of memory and other resources
-* Exiting without calling destructors
-* Integer overflow
-  - Overflow is considered "unexpected" behavior and is always user-error,
-    unless the `wrapping` primitives are used. In non-optimized builds, the compiler
-    will insert debug checks that panic on overflow, but in optimized builds overflow
-    instead results in wrapped values. See [RFC 560] for the rationale and more details.
-
-[RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md
-
 #### Diverging functions
 
 A special kind of function can be declared with a `!` character where the
@@ -1155,9 +1074,9 @@ type Point = (u8, u8);
 let p: Point = (41, 68);
 ```
 
-### Structures
+### Structs
 
-A _structure_ is a nominal [structure type](#structure-types) defined with the
+A _struct_ is a nominal [struct type](#struct-types) defined with the
 keyword `struct`.
 
 An example of a `struct` item and its use:
@@ -1168,7 +1087,7 @@ let p = Point {x: 10, y: 11};
 let px: i32 = p.x;
 ```
 
-A _tuple structure_ is a nominal [tuple type](#tuple-types), also defined with
+A _tuple struct_ is a nominal [tuple type](#tuple-types), also defined with
 the keyword `struct`. For example:
 
 ```
@@ -1177,15 +1096,26 @@ let p = Point(10, 11);
 let px: i32 = match p { Point(x, _) => x };
 ```
 
-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. For example:
+A _unit-like struct_ is a struct without any fields, defined by leaving off
+the list of fields entirely. Such a struct implicitly defines a constant of
+its type with the same name. For example:
 
 ```
+# #![feature(braced_empty_structs)]
 struct Cookie;
-let c = [Cookie, Cookie, Cookie, Cookie];
+let c = [Cookie, Cookie {}, Cookie, Cookie {}];
+```
+
+is equivalent to
+
+```
+# #![feature(braced_empty_structs)]
+struct Cookie {}
+const Cookie: Cookie = Cookie {};
+let c = [Cookie, Cookie {}, Cookie, Cookie {}];
 ```
 
-The precise memory layout of a structure is not specified. One can specify a
+The precise memory layout of a struct is not specified. One can specify a
 particular layout using the [`repr` attribute](#ffi-attributes).
 
 ### Enumerations
@@ -1508,11 +1438,11 @@ struct Foo;
 
 trait Shape { fn area(&self) -> f64; }
 trait Circle : Shape { fn radius(&self) -> f64; }
-impl Shape for Foo {
-    fn area(&self) -> f64 {
-        0.0
-    }
-}
+impl Shape for Foo {
+    fn area(&self) -> f64 {
+        0.0
+    }
+}
 impl Circle for Foo {
     fn radius(&self) -> f64 {
         println!("calling area: {}", self.area());
@@ -1590,11 +1520,11 @@ impl Shape for Circle {
 ```
 
 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 crate as the `self` type:
+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, trait objects), and the implementation must
+appear in the same crate as the `self` type:
 
 ```
 struct Point {x: i32, y: i32}
@@ -1977,7 +1907,7 @@ On `struct`s:
   list of names `#[macro_use(foo, bar)]` restricts the import to just those
   macros named.  The `extern crate` must appear at the crate root, not inside
   `mod`, which ensures proper function of the [`$crate` macro
-  variable](book/macros.html#the-variable-$crate).
+  variable](book/macros.html#the-variable-crate).
 
 - `macro_reexport` on an `extern crate` — re-export the named macros.
 
@@ -1987,7 +1917,7 @@ On `struct`s:
   link it into the output.
 
 See the [macros section of the
-book](book/macros.html#scoping-and-macro-import/export) for more information on
+book](book/macros.html#scoping-and-macro-importexport) for more information on
 macro scope.
 
 
@@ -2002,6 +1932,20 @@ macro scope.
 - `simd` - on certain tuple structs, derive the arithmetic operators, which
   lower to the target's SIMD instructions, if any; the `simd` feature gate
   is necessary to use this attribute.
+- `unsafe_destructor_blind_to_params` - on `Drop::drop` method, asserts that the
+  destructor code (and all potential specializations of that code) will
+  never attempt to read from nor write to any references with lifetimes
+  that come in via generic parameters. This is a constraint we cannot
+  currently express via the type system, and therefore we rely on the
+  programmer to assert that it holds. Adding this to a Drop impl causes
+  the associated destructor to be considered "uninteresting" by the
+  Drop-Check rule, and thus it can help sidestep data ordering
+  constraints that would otherwise be introduced by the Drop-Check
+  rule. Such sidestepping of the constraints, if done incorrectly, can
+  lead to undefined behavior (in the form of reading or writing to data
+  outside of its dynamic extent), and thus this attribute has the word
+  "unsafe" in its name. To use this, the
+  `unsafe_destructor_blind_to_params` feature gate must be enabled.
 - `unsafe_no_drop_flag` - on structs, remove the flag that prevents
   destructors from being run twice. Destructors might be run multiple times on
   the same object with this attribute. To use this, the `unsafe_no_drop_flag` feature
@@ -2081,6 +2025,8 @@ The following configurations must be defined by the implementation:
 * `target_pointer_width = "..."` - Target pointer width in bits. This is set
   to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for
   64-bit pointers.
+* `target_vendor = "..."` - Vendor of the target, for example `apple`, `pc`, or
+  simply `"unknown"`.
 * `test` - Enabled when compiling the test harness (using the `--test` flag).
 * `unix` - See `target_family`.
 * `windows` - See `target_family`.
@@ -2257,7 +2203,7 @@ The currently implemented features of the reference compiler are:
 * `advanced_slice_patterns` - See the [match expressions](#match-expressions)
                               section for discussion; the exact semantics of
                               slice patterns are subject to change, so some types
-                             are still unstable.
+                              are still unstable.
 
 * `slice_patterns` - OK, actually, slice patterns are just scary and
                      completely unstable.
@@ -2278,6 +2224,9 @@ The currently implemented features of the reference compiler are:
 * `box_syntax` - Allows use of `box` expressions, the exact semantics of which
                  is subject to change.
 
+* `cfg_target_vendor` - Allows conditional compilation using the `target_vendor`
+                        matcher which is subject to change.
+
 * `concat_idents` - Allows use of the `concat_idents` macro, which is in many
                     ways insufficient for concatenating identifiers, and may be
                     removed entirely for something more wholesome.
@@ -2411,6 +2360,7 @@ The currently implemented features of the reference compiler are:
                               terms of encapsulation).
 * - `default_type_parameter_fallback` - Allows type parameter defaults to
                                         influence type inference.
+* - `braced_empty_structs` - Allows use of empty structs and enum variants with braces.
 
 If a feature is promoted to a language feature, then all existing programs will
 start to receive compilation warnings about `#![feature]` directives which enabled
@@ -2454,7 +2404,7 @@ items.
 
 An _item declaration statement_ has a syntactic form identical to an
 [item](#items) declaration within a module. Declaring an item &mdash; a
-function, enumeration, structure, type, static, trait, implementation or module
+function, enumeration, struct, type, static, trait, implementation or module
 &mdash; 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.
@@ -2560,7 +2510,7 @@ Here are some examples:
 #### Moved and copied types
 
 When a [local variable](#variables) is used as an
-[rvalue](#lvalues,-rvalues-and-temporaries), the variable will be copied
+[rvalue](#lvalues-rvalues-and-temporaries), the variable will be copied
 if its type implements `Copy`. All others are moved.
 
 ### Literal expressions
@@ -2579,7 +2529,7 @@ value, or the unit value.
 ### Path expressions
 
 A [path](#paths) used as an expression context denotes either a local variable
-or an item. Path expressions are [lvalues](#lvalues,-rvalues-and-temporaries).
+or an item. Path expressions are [lvalues](#lvalues-rvalues-and-temporaries).
 
 ### Tuple expressions
 
@@ -2599,26 +2549,26 @@ comma:
 (0); // zero in parentheses
 ```
 
-### Structure expressions
+### Struct expressions
 
-There are several forms of structure expressions. A _structure expression_
-consists of the [path](#paths) of a [structure item](#structures), followed by
+There are several forms of struct expressions. A _struct expression_
+consists of the [path](#paths) of a [struct item](#structs), 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
+providing the field values of a new instance of the struct. 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.
+The location denoted by a struct field is mutable if and only if the
+enclosing struct is mutable.
 
-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
+A _tuple struct expression_ consists of the [path](#paths) of a [struct
+item](#structs), followed by a parenthesized list of one or more
+comma-separated expressions (in other words, the path of a struct item
+followed by a tuple expression). The struct item must be a tuple struct
 item.
 
-A _unit-like structure expression_ consists only of the [path](#paths) of a
-[structure item](#structures).
+A _unit-like struct expression_ consists only of the [path](#paths) of a
+[struct item](#structs).
 
-The following are examples of structure expressions:
+The following are examples of struct expressions:
 
 ```
 # struct Point { x: f64, y: f64 }
@@ -2631,14 +2581,14 @@ let u = game::User {name: "Joe", age: 35, score: 100_000};
 some_fn::<Cookie>(Cookie);
 ```
 
-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
+A struct expression forms a new value of the named struct type. Note
+that for a given *unit-like* struct type, this will always be the same
 value.
 
-A structure expression can terminate with the syntax `..` followed by an
+A struct 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 constructing a new structure (with
+base) must have the same struct type as the new struct type being formed.
+The entire expression denotes the result of constructing a new struct (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 expression for all other
 fields.
@@ -2684,7 +2634,7 @@ the left-hand-side expression is an indirect [trait object](#trait-objects).
 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).
+expression denotes a field of a [struct](#struct-types).
 
 ```{.ignore .field}
 mystruct.myfield;
@@ -2692,7 +2642,7 @@ foo().x;
 (Struct {a: 10, b: 20}).a;
 ```
 
-A field access is an [lvalue](#lvalues,-rvalues-and-temporaries) referring to
+A field access is an [lvalue](#lvalues-rvalues-and-temporaries) referring to
 the value of that field. When the type providing the field inherits mutability,
 it can be [assigned](#assignment-expressions) to.
 
@@ -2703,7 +2653,7 @@ fewer autoderefs to more.
 
 ### Array expressions
 
-An [array](#array,-and-slice-types) _expression_ is written by enclosing zero
+An [array](#array-and-slice-types) _expression_ is written by enclosing zero
 or more comma-separated expressions of uniform type in square brackets.
 
 In the `[expr ';' expr]` form, the expression after the `';'` must be a
@@ -2719,9 +2669,9 @@ constant expression that can be evaluated at compile time, such as a
 
 ### Index expressions
 
-[Array](#array,-and-slice-types)-typed expressions can be indexed by
+[Array](#array-and-slice-types)-typed expressions can be indexed by
 writing a square-bracket-enclosed expression (the index) after them. When the
-array is mutable, the resulting [lvalue](#lvalues,-rvalues-and-temporaries) can
+array is mutable, the resulting [lvalue](#lvalues-rvalues-and-temporaries) can
 be assigned to.
 
 Indices are zero-based, and may be of any integral type. Vector access is
@@ -2762,7 +2712,7 @@ The following expressions are equivalent.
 let x = std::ops::Range {start: 0, end: 10};
 let y = 0..10;
 
-assert_eq!(x,y);
+assert_eq!(x, y);
 ```
 
 ### Unary operator expressions
@@ -2775,7 +2725,7 @@ before the expression they apply to.
 * `*`
   : Dereference. When applied to a [pointer](#pointer-types) it denotes the
     pointed-to location. For pointers to mutable locations, the resulting
-    [lvalue](#lvalues,-rvalues-and-temporaries) can be assigned to.
+    [lvalue](#lvalues-rvalues-and-temporaries) can be assigned to.
     On non-pointer types, it calls the `deref` method of the `std::ops::Deref`
     trait, or the `deref_mut` method of the `std::ops::DerefMut` trait (if
     implemented by the type and required for an outer expression that will or
@@ -2916,8 +2866,8 @@ surprising side-effects on the dynamic execution semantics.
 #### Assignment expressions
 
 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.
+[lvalue](#lvalues-rvalues-and-temporaries) expression followed by an equals
+sign (`=`) and an [rvalue](#lvalues-rvalues-and-temporaries) expression.
 
 Evaluating an assignment expression [either copies or
 moves](#moved-and-copied-types) its right-hand operand to its left-hand
@@ -3035,10 +2985,10 @@ A `loop` expression may optionally have a _label_. The label is written as
 a lifetime preceding the loop expression, as in `'foo: loop{ }`. If a
 label is present, then labeled `break` and `continue` expressions nested
 within this loop may exit out of this loop or return control to its head.
-See [Break expressions](#break-expressions) and [Continue
+See [break expressions](#break-expressions) and [continue
 expressions](#continue-expressions).
 
-### Break expressions
+### `break` expressions
 
 A `break` expression has an optional _label_. If the label is absent, then
 executing a `break` expression immediately terminates the innermost loop
@@ -3046,7 +2996,7 @@ 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.
 
-### Continue expressions
+### `continue` expressions
 
 A `continue` expression has an optional _label_. If the label is absent, then
 executing a `continue` expression immediately terminates the current iteration
@@ -3059,7 +3009,7 @@ innermost label enclosing the `break` expression, but must enclose it.
 
 A `continue` expression is only permitted in the body of a loop.
 
-### While loops
+### `while` loops
 
 A `while` loop begins by evaluating the boolean loop conditional expression.
 If the loop conditional expression evaluates to `true`, the loop body block
@@ -3082,12 +3032,12 @@ Like `loop` expressions, `while` loops can be controlled with `break` or
 loops](#infinite-loops), [break expressions](#break-expressions), and
 [continue expressions](#continue-expressions) for more information.
 
-### For expressions
+### `for` expressions
 
 A `for` expression is a syntactic construct for looping over elements provided
 by an implementation of `std::iter::IntoIterator`.
 
-An example of a for loop over the contents of an array:
+An example of a `for` loop over the contents of an array:
 
 ```
 # type Foo = i32;
@@ -3117,7 +3067,7 @@ Like `loop` expressions, `for` loops can be controlled with `break` or
 loops](#infinite-loops), [break expressions](#break-expressions), and
 [continue expressions](#continue-expressions) for more information.
 
-### If expressions
+### `if` expressions
 
 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
@@ -3129,11 +3079,11 @@ 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.
 
-### Match expressions
+### `match` expressions
 
 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 arrays or enum constructors, structures and tuples,
+literals, destructured arrays or enum constructors, structs 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
@@ -3144,7 +3094,7 @@ stands for a *single* data field, whereas a wildcard `..` stands for *all* the
 fields of a particular variant.
 
 A `match` behaves differently depending on whether or not the head expression
-is an [lvalue or an rvalue](#lvalues,-rvalues-and-temporaries). If the head
+is an [lvalue or an rvalue](#lvalues-rvalues-and-temporaries). If the head
 expression is an rvalue, it is first evaluated into a temporary location, and
 the resulting 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
@@ -3235,7 +3185,7 @@ let message = match maybe_digit {
 };
 ```
 
-### If let expressions
+### `if let` expressions
 
 An `if let` expression is semantically identical to an `if` expression but in place
 of a condition expression it expects a refutable let statement. If the value of the
@@ -3256,7 +3206,7 @@ if let ("Ham", b) = dish {
 }
 ```
 
-### While let loops
+### `while let` loops
 
 A `while let` loop is semantically identical to a `while` loop but in place of a
 condition expression it expects a refutable let statement. If the value of the
@@ -3264,7 +3214,7 @@ expression on the right hand side of the let statement matches the pattern, the
 loop body block executes and control returns to the pattern matching statement.
 Otherwise, the while expression completes.
 
-### Return expressions
+### `return` expressions
 
 Return expressions are denoted with the keyword `return`. Evaluating a `return`
 expression moves its argument into the designated output location for the
@@ -3403,17 +3353,17 @@ As you can see, the `vec!` macro allows you to create a `Vec<T>` easily. The
 All in-bounds elements of arrays and slices are always initialized, and access
 to an array or slice is always bounds-checked.
 
-### Structure types
+### Struct types
 
 A `struct` *type* is a heterogeneous product of other types, called the
 *fields* of the type.[^structtype]
 
 [^structtype]: `struct` types are analogous to `struct` types in C,
     the *record* types of the ML family,
-    or the *structure* types of the Lisp family.
+    or the *struct* types of the Lisp family.
 
 New instances of a `struct` can be constructed with a [struct
-expression](#structure-expressions).
+expression](#struct-expressions).
 
 The memory layout of a `struct` is undefined by default to allow for compiler
 optimizations like field reordering, but it can be fixed with the
@@ -3423,14 +3373,14 @@ have the same memory layout.
 
 The fields of a `struct` may be qualified by [visibility
 modifiers](#visibility-and-privacy), to allow access to data in a
-structure outside a module.
+struct outside a module.
 
-A _tuple struct_ type is just like a structure type, except that the fields are
+A _tuple struct_ type is just like a struct type, except that the fields are
 anonymous.
 
-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-expressions) is the only value that inhabits such a
+A _unit-like struct_ type is like a struct type, except that it has no
+fields. The one value constructed by the associated [struct
+expression](#struct-expressions) is the only value that inhabits such a
 type.
 
 ### Enumerated types
@@ -3457,13 +3407,13 @@ named reference to an [`enum` item](#enumerations).
 ### Recursive types
 
 Nominal types &mdash; [enumerations](#enumerated-types) and
-[structures](#structure-types) &mdash; may be recursive. That is, each `enum`
+[structs](#struct-types) &mdash; 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:
 
 * Recursive types must include a nominal type in the recursion
   (not mere [type definitions](grammar.html#type-definitions),
-   or other structural types such as [arrays](#array,-and-slice-types) or [tuples](#tuple-types)).
+   or other structural types such as [arrays](#array-and-slice-types) or [tuples](#tuple-types)).
 * A recursive `enum` item must have at least one non-recursive constructor
   (in order to give the recursion a basis case).
 * The size of a recursive type must be finite;
@@ -3485,7 +3435,7 @@ let a: List<i32> = List::Cons(7, Box::new(List::Cons(13, Box::new(List::Nil))));
 ### Pointer types
 
 All pointers in Rust are explicit first-class values. They can be copied,
-stored into data structures, and returned from functions. There are two
+stored into data structs, and returned from functions. There are two
 varieties of pointer in Rust:
 
 * References (`&`)
@@ -3759,7 +3709,7 @@ repeated sub-expression is a coercion site for coercion to type `U`.
 Each sub-expression is a coercion site to the respective type, e.g. the
 zeroth sub-expression is a coercion site to type `U_0`.
 
-* Parenthesised sub-expressions (`(e)`): if the expression has type `U`, then
+* Parenthesized sub-expressions (`(e)`): if the expression has type `U`, then
 the sub-expression is a coercion site to `U`.
 
 * Blocks: if a block has type `U`, then the last expression in the block (if
@@ -3885,7 +3835,7 @@ references to boxes are dropped.
 ### Variables
 
 A _variable_ is a component of a stack frame, either a named function parameter,
-an anonymous [temporary](#lvalues,-rvalues-and-temporaries), or a named local
+an anonymous [temporary](#lvalues-rvalues-and-temporaries), or a named local
 variable.
 
 A _local variable_ (or *stack-local* allocation) holds a value directly,
@@ -3919,11 +3869,11 @@ initialized; this is enforced by the compiler.
 The Rust compiler supports various methods to link crates together both
 statically and dynamically. This section will explore the various methods to
 link Rust crates together, and more information about native libraries can be
-found in the [ffi section of the book][ffi].
+found in the [FFI section of the book][ffi].
 
 In one session of compilation, the compiler can generate multiple artifacts
 through the usage of either command line flags or the `crate_type` attribute.
-If one or more command line flag is specified, all `crate_type` attributes will
+If one or more command line flags are specified, all `crate_type` attributes will
 be ignored in favor of only building the artifacts specified by command line.
 
 * `--crate-type=bin`, `#[crate_type = "bin"]` - A runnable executable will be
@@ -3969,7 +3919,7 @@ Note that these outputs are stackable in the sense that if multiple are
 specified, then the compiler will produce each form of output at once without
 having to recompile. However, this only applies for outputs specified by the
 same method. If only `crate_type` attributes are specified, then they will all
-be built, but if one or more `--crate-type` command line flag is specified,
+be built, but if one or more `--crate-type` command line flags are specified,
 then only those outputs will be built.
 
 With all these different kinds of outputs, if crate A depends on crate B, then
@@ -4024,9 +3974,98 @@ In general, `--crate-type=bin` or `--crate-type=lib` should be sufficient for
 all compilation needs, and the other options are just available if more
 fine-grained control is desired over the output format of a Rust crate.
 
-# Appendix: Rationales and design trade-offs
+# Unsafety
+
+Unsafe operations are those that potentially violate the memory-safety
+guarantees of Rust's static semantics.
+
+The following language level features cannot be used in the safe subset of
+Rust:
+
+- Dereferencing a [raw pointer](#pointer-types).
+- Reading or writing a [mutable static variable](#mutable-statics).
+- Calling an unsafe function (including an intrinsic or foreign function).
+
+## Unsafe functions
+
+Unsafe functions are functions that are not safe in all contexts and/or for all
+possible inputs. Such a function must be prefixed with the keyword `unsafe` and
+can only be called from an `unsafe` block or another `unsafe` function.
+
+## Unsafe blocks
+
+A block of code can be prefixed with the `unsafe` keyword, to permit calling
+`unsafe` functions or dereferencing raw pointers within a safe function.
+
+When a programmer has sufficient conviction that a sequence of potentially
+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, in the surrounding context.
+
+Unsafe blocks are used to wrap foreign libraries, make direct use of hardware
+or implement features not directly present in the language. For example, Rust
+provides the language features necessary to implement memory-safe concurrency
+in the language but the implementation of threads and message passing is in the
+standard library.
+
+Rust's type system is a conservative approximation of the dynamic safety
+requirements, so in some cases there is a performance cost to using safe code.
+For example, a doubly-linked list is not a tree structure and can only be
+represented with reference-counted pointers in safe code. By using `unsafe`
+blocks to represent the reverse links as raw pointers, it can be implemented
+with only boxes.
+
+## Behavior considered undefined
+
+The following is a list of behavior which is forbidden in all Rust code,
+including within `unsafe` blocks and `unsafe` functions. Type checking provides
+the guarantee that these issues are never caused by safe code.
 
-*TODO*.
+* Data races
+* Dereferencing a null/dangling raw pointer
+* Reads of [undef](http://llvm.org/docs/LangRef.html#undefined-values)
+  (uninitialized) memory
+* Breaking the [pointer aliasing
+  rules](http://llvm.org/docs/LangRef.html#pointer-aliasing-rules)
+  with raw pointers (a subset of the rules used by C)
+* `&mut` and `&` follow LLVM’s scoped [noalias] model, except if the `&T`
+  contains an `UnsafeCell<U>`. Unsafe code must not violate these aliasing
+  guarantees.
+* Mutating non-mutable data (that is, data reached through a shared reference or
+  data owned by a `let` binding), unless that data is contained within an `UnsafeCell<U>`.
+* Invoking undefined behavior via compiler intrinsics:
+  * Indexing outside of the bounds of an object with `std::ptr::offset`
+    (`offset` intrinsic), with
+    the exception of one byte past the end which is permitted.
+  * Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64`
+    intrinsics) on overlapping buffers
+* Invalid values in primitive types, even in private fields/locals:
+  * Dangling/null references or boxes
+  * A value other than `false` (0) or `true` (1) in a `bool`
+  * A discriminant in an `enum` not included in the type definition
+  * A value in a `char` which is a surrogate or above `char::MAX`
+  * Non-UTF-8 byte sequences in a `str`
+* Unwinding into Rust from foreign code or unwinding from Rust into foreign
+  code. Rust's failure system is not compatible with exception handling in
+  other languages. Unwinding must be caught and handled at FFI boundaries.
+
+[noalias]: http://llvm.org/docs/LangRef.html#noalias
+
+## Behavior not considered unsafe
+
+This is a list of behavior not considered *unsafe* in Rust terms, but that may
+be undesired.
+
+* Deadlocks
+* Leaks of memory and other resources
+* Exiting without calling destructors
+* Integer overflow
+  - Overflow is considered "unexpected" behavior and is always user-error,
+    unless the `wrapping` primitives are used. In non-optimized builds, the compiler
+    will insert debug checks that panic on overflow, but in optimized builds overflow
+    instead results in wrapped values. See [RFC 560] for the rationale and more details.
+
+[RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md
 
 # Appendix: Influences
 
@@ -4036,7 +4075,7 @@ that have since been removed):
 
 * SML, OCaml: algebraic data types, pattern matching, type inference,
   semicolon statement separation
-* C++: references, RAII, smart pointers, move semantics, monomorphisation,
+* C++: references, RAII, smart pointers, move semantics, monomorphization,
   memory model
 * ML Kit, Cyclone: region based memory management
 * Haskell (GHC): typeclasses, type families
index 6204f38a37753ce603b4e830c8aae400c5b360c3..874f69766196fc589477d3e2d54a91fd45a38e44 100644 (file)
@@ -338,14 +338,17 @@ table th {
 
 .rusttest { display: none; }
 pre.rust { position: relative; }
-.test-arrow {
+a.test-arrow {
     display: inline-block;
     position: absolute;
-    top: 0;
-    right: 10px;
-    font-size: 150%;
-    -webkit-transform: scaleX(-1);
-    transform: scaleX(-1);
+
+    background-color: #4e8bca;
+    color: #f5f5f5;
+    padding: 5px 10px 5px 10px;
+    border-radius: 5px;
+    font-size: 130%;
+    top: 5px;
+    right: 5px;
 }
 
 .unstable-feature {
index 41bc08f229e7c9f65f5120d82507ca216da21c8e..508ede6c4a0ac5b768022f5b746f97f7570912d4 100644 (file)
@@ -48,7 +48,3 @@
 * [Testing](testing/README.md)
     * [Unit testing](testing/unit.md)
 * [FFI, platform-specific code](platform.md)
-* [APIs for a changing Rust](changing/README.md)
-    * [Pre-1.0 changes](changing/pre-1-0.md)
-    * [Post-1.0 changes](changing/post-1-0.md)
-    * [Timing unclear](changing/unclear.md)
diff --git a/src/doc/style/changing/README.md b/src/doc/style/changing/README.md
deleted file mode 100644 (file)
index 38e76f6..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-% API design for a changing Rust
-
-A number of planned Rust features will drastically affect the API design
-story. This section collects some of the biggest features with concrete examples
-of how the API will change.
diff --git a/src/doc/style/changing/post-1-0.md b/src/doc/style/changing/post-1-0.md
deleted file mode 100644 (file)
index 7ac1c83..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-% Post-1.0 changes
-
-### Higher-kinded types
-
-* A trait encompassing both `Iterable<T>` for some fixed `T` and
-  `FromIterator<U>` for _all_ `U` (where HKT comes in).  The train
-  could provide e.g. a default `map` method producing the same kind of
-  the container, but with a new type parameter.
-
-* **Monadic-generic programming**? Can we add this without deprecating
-  huge swaths of the API (including `Option::map`, `option::collect`,
-  `result::collect`, `try!` etc.
diff --git a/src/doc/style/changing/pre-1-0.md b/src/doc/style/changing/pre-1-0.md
deleted file mode 100644 (file)
index adadfe3..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-% Pre-1.0 changes
-
-### `std` facade
-
-We should revisit some APIs in `libstd` now that the facade effort is complete.
-
-For example, the treatment of environment variables in the new
-`Command` API is waiting on access to hashtables before being
-approved.
-
-### Trait reform
-
-Potential for standard conversion traits (`to`, `into`, `as`).
-
-Probably many other opportunities here.
-
-### Unboxed closures
diff --git a/src/doc/style/changing/unclear.md b/src/doc/style/changing/unclear.md
deleted file mode 100644 (file)
index e4b8a98..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-% Changes with unclear timing
-
-### Associated items
-
-* Many traits that currently take type parameters should instead use associated
-  types; this will _drastically_ simplify signatures in some cases.
-
-* Associated constants would be useful in a few places, e.g. traits for
-  numerics, traits for paths.
-
-### Anonymous, unboxed return types (aka `impl Trait` types)
-
-* See https://github.com/rust-lang/rfcs/pull/105
-
-* Could affect API design in several places, e.g. the `Iterator` trait.
-
-### Default type parameters
-
-We are already using this in a few places (e.g. `HashMap`), but it's
-feature-gated.
-
-### Compile-time function evaluation (CTFE)
-
-https://github.com/mozilla/rust/issues/11621
-
-### Improved constant folding
-
-https://github.com/rust-lang/rust/issues/7834
index 0985475f56a9a86e43ee3c5b101e4ea49bab3a22..a404d25bf370353cc5f07202ad531d653ce9b2c9 100644 (file)
@@ -57,7 +57,7 @@ fn write_info(info: &Info) -> Result<(), IoError> {
 ```
 
 See
-[the `result` module documentation](https://doc.rust-lang.org/stable/std/result/index.html#the-try!-macro)
+[the `result` module documentation](https://doc.rust-lang.org/stable/std/result/index.html#the-try-macro)
 for more details.
 
 ### The `Result`-`impl` pattern [FIXME]
index 23d8760f571f6cecca166e4d81d251e77169e335..c55b38b915b3d1d9e6241d324cee7fec6a003271 100644 (file)
@@ -17,12 +17,12 @@ Organize module headers as follows:
 Avoid using `#[path="..."]` directives; make the file system and
 module hierarchy match, instead.
 
-### Use the module hirearchy to organize APIs into coherent sections. [FIXME]
+### Use the module hierarchy to organize APIs into coherent sections. [FIXME]
 
 > **[FIXME]** Flesh this out with examples; explain what a "coherent
 > section" is with examples.
 >
-> The module hirearchy defines both the public and internal API of your module.
+> The module hierarchy defines both the public and internal API of your module.
 > Breaking related functionality into submodules makes it understandable to both
 > users and contributors to the module.
 
@@ -82,7 +82,7 @@ io/mod.rs
 ```
 
 While it is possible to define all of `io` within a single directory,
-mirroring the module hirearchy in the directory structure makes
+mirroring the module hierarchy in the directory structure makes
 submodules of `io::net` easier to find.
 
 ### Consider top-level definitions or reexports. [FIXME: needs RFC]
@@ -104,13 +104,13 @@ while
 [`TcpStream`](https://doc.rust-lang.org/std/io/net/tcp/struct.TcpStream.html)
 is defined in `io/net/tcp.rs` and reexported in the `io` module.
 
-### Use internal module hirearchies for organization. [FIXME: needs RFC]
+### Use internal module hierarchies for organization. [FIXME: needs RFC]
 
 > **[FIXME]**
 > - Referencing internal modules from the standard library is subject to
 >   becoming outdated.
 
-Internal module hirearchies (i.e., private submodules) may be used to
+Internal module hierarchies (i.e., private submodules) may be used to
 hide implementation details that are not part of the module's API.
 
 For example, in [`std::io`](https://doc.rust-lang.org/std/io/), `mod mem`
index 48c37eabcaaa13ab200aa90da74a281e2758501b..18346c092547fbe822abc206fed0d4d74e198d7a 100644 (file)
@@ -9,18 +9,18 @@ applicable, common traits.
 
 To see why, consider the following situation:
 
-* Crate `std` defines trait `Show`.
-* Crate `url` defines type `Url`, without implementing `Show`.
+* Crate `std` defines trait `Debug`.
+* Crate `url` defines type `Url`, without implementing `Debug`.
 * Crate `webapp` imports from both `std` and `url`,
 
-There is no way for `webapp` to add `Show` to `url`, since it defines neither.
+There is no way for `webapp` to add `Debug` to `url`, since it defines neither.
 (Note: the newtype pattern can provide an efficient, but inconvenient
 workaround; see [newtype for views](../types/newtype.md))
 
 The most important common traits to implement from `std` are:
 
 ```rust
-Clone, Show, Hash, Eq
+Clone, Debug, Hash, Eq
 ```
 
 #### When safe, derive or otherwise implement `Send` and `Share`. [FIXME]
index 2d9356fc42d1d46ed0012c7ffa7716154f3f9ea3..26ffda50ac53dc1a06b30dae8e7b0fc4e2a82d52 100644 (file)
@@ -27,7 +27,7 @@ explicitly implement to be used by this generic function.
 * _Inference_. Since the type parameters to generic functions can usually be
   inferred, generic functions can help cut down on verbosity in code where
   explicit conversions or other method calls would usually be necessary. See the
-  [overloading/implicits use case](#use-case:-limited-overloading-and/or-implicit-conversions)
+  [overloading/implicits use case](#use-case-limited-overloading-andor-implicit-conversions)
   below.
 * _Precise types_. Because generics give a _name_ to the specific type
   implementing a trait, it is possible to be precise about places where that
@@ -51,7 +51,7 @@ explicitly implement to be used by this generic function.
   a `Vec<T>` contains elements of a single concrete type (and, indeed, the
   vector representation is specialized to lay these out in line). Sometimes
   heterogeneous collections are useful; see
-  [trait objects](#use-case:-trait-objects) below.
+  [trait objects](#use-case-trait-objects) below.
 * _Signature verbosity_. Heavy use of generics can bloat function signatures.
   **[Ed. note]** This problem may be mitigated by some language improvements; stay tuned.
 
index 61f8db87cde8983fc068c154614f24fef95324e4..feedd3937fc9dcac67e804cff5ced6af966c177e 100644 (file)
@@ -5,7 +5,7 @@
 > **[FIXME]** We probably want to discourage this, at least when used in a way
 > that is publicly exposed.
 
-Traits that provide default implmentations for function can provide code reuse
+Traits that provide default implementations for function can provide code reuse
 across types. For example, a `print` method can be defined across multiple
 types as follows:
 
index b2d2d9ab6b4d68e1a776797112ea3988b38b435e..3851187b520349e09cb5150775b06bbc6cc212a2 100644 (file)
@@ -85,3 +85,20 @@ Use inner doc comments _only_ to document crates and file-level modules:
 //!
 //! The core library is a something something...
 ```
+
+### Explain context.
+
+Rust doesn't have special constructors, only functions that return new
+instances.  These aren't visible in the automatically generated documentation
+for a type, so you should specifically link to them:
+
+``` rust
+/// An iterator that yields `None` forever after the underlying iterator
+/// yields `None` once.
+///
+/// These can be created through
+/// [`iter.fuse()`](trait.Iterator.html#method.fuse).
+pub struct Fuse<I> {
+    // ...
+}
+```
index 0feaf9c6bbfd97fbe93a8c59cfbffde6b57c1596..6962f828e194d836255427b3a1b437c1be4af3ae 100644 (file)
@@ -9,9 +9,8 @@ requirements, and writing low-level code, like device drivers and operating
 systems. It improves on current languages targeting this space by having a
 number of compile-time safety checks that produce no runtime overhead, while
 eliminating all data races. Rust also aims to achieve ‘zero-cost abstractions’
-even though some of these abstractions feel like those of a high-level
-language. Even then, Rust still allows precise control like a low-level
-language would.
+even though some of these abstractions feel like those of a high-level language.
+Even then, Rust still allows precise control like a low-level language would.
 
 [rust]: https://www.rust-lang.org
 
@@ -34,15 +33,15 @@ is the first. After this:
 [gl]: glossary.html
 [bi]: bibliography.html
 
-After reading this introduction, you’ll want to dive into either ‘Learn Rust’
-or ‘Syntax and Semantics’, depending on your preference: ‘Learn Rust’ if you
-want to dive in with a project, or ‘Syntax and Semantics’ if you prefer to
-start small, and learn a single concept thoroughly before moving onto the next.
+After reading this introduction, you’ll want to dive into either ‘Learn Rust’ or
+‘Syntax and Semantics’, depending on your preference: ‘Learn Rust’ if you want
+to dive in with a project, or ‘Syntax and Semantics’ if you prefer to start
+small, and learn a single concept thoroughly before moving onto the next.
 Copious cross-linking connects these parts together.
 
 ### Contributing
 
-The source files from which this book is generated can be found on Github:
+The source files from which this book is generated can be found on GitHub:
 [github.com/rust-lang/rust/tree/master/src/doc/trpl](https://github.com/rust-lang/rust/tree/master/src/doc/trpl)
 
 ## A brief introduction to Rust
@@ -76,11 +75,11 @@ type inference to balance out the power of static typing with the verbosity of
 annotating types.
 
 Rust prefers stack allocation to heap allocation: `x` is placed directly on the
-stack. However, the `Vec<T>` type allocates space for the elements of the
-vector on the heap. If you’re not familiar with this distinction, you can
-ignore it for now, or check out [‘The Stack and the Heap’][heap]. As a systems
-programming language, Rust gives you the ability to control how your memory is
-allocated, but when we’re getting started, it’s less of a big deal.
+stack. However, the `Vec<T>` type allocates space for the elements of the vector
+on the heap. If you’re not familiar with this distinction, you can ignore it for
+now, or check out [‘The Stack and the Heap’][heap]. As a systems programming
+language, Rust gives us the ability to control how our memory is allocated, but
+when we’re getting started, it’s less of a big deal.
 
 [var]: variable-bindings.html
 [macro]: macros.html
@@ -90,10 +89,10 @@ Earlier, we mentioned that ‘ownership’ is the key new concept in Rust. In Ru
 parlance, `x` is said to ‘own’ the vector. This means that when `x` goes out of
 scope, the vector’s memory will be de-allocated. This is done deterministically
 by the Rust compiler, rather than through a mechanism such as a garbage
-collector. In other words, in Rust, you don’t call functions like `malloc` and
-`free` yourself: the compiler statically determines when you need to allocate
-or deallocate memory, and inserts those calls itself. To err is to be human,
-but compilers never forget.
+collector. In other words, in Rust, we don’t call functions like `malloc` and
+`free` ourselves: the compiler statically determines when we need to allocate or
+deallocate memory, and inserts those calls itself. To err is to be human, but
+compilers never forget.
 
 Let’s add another line to our example:
 
@@ -105,13 +104,13 @@ fn main() {
 }
 ```
 
-We’ve introduced another binding, `y`. In this case, `y` is a ‘reference’ to
-the first element of the vector. Rust’s references are similar to pointers in
-other languages, but with additional compile-time safety checks. References
-interact with the ownership system by [‘borrowing’][borrowing] what they point
-to, rather than owning it. The difference is, when the reference goes out of
-scope, it will not deallocate the underlying memory. If it did, we’d
-de-allocate twice, which is bad!
+We’ve introduced another binding, `y`. In this case, `y` is a ‘reference’ to the
+first element of the vector. Rust’s references are similar to pointers in other
+languages, but with additional compile-time safety checks. References interact
+with the ownership system by [‘borrowing’][borrowing] what they point to, rather
+than owning it. The difference is, when the reference goes out of scope, it
+won't deallocate the underlying memory. If it did, we’d de-allocate twice, which
+is bad!
 
 [borrowing]: references-and-borrowing.html
 
@@ -147,7 +146,7 @@ fn main() {
 
 Whew! The Rust compiler gives quite detailed errors at times, and this is one
 of those times. As the error explains, while we made our binding mutable, we
-still cannot call `push`. This is because we already have a reference to an
+still can't call `push`. This is because we already have a reference to an
 element of the vector, `y`. Mutating something while another reference exists
 is dangerous, because we may invalidate the reference. In this specific case,
 when we create the vector, we may have only allocated space for two elements.
index ae2416018c8f7e193145a7aaa8689abc8baf9630..2b5d1fa70aada5fd59ab9da5aab5ea439d4f0a17 100644 (file)
@@ -68,5 +68,7 @@
     * [Box Syntax and Patterns](box-syntax-and-patterns.md)
     * [Slice Patterns](slice-patterns.md)
     * [Associated Constants](associated-constants.md)
+    * [Custom Allocators](custom-allocators.md)
 * [Glossary](glossary.md)
+* [Syntax Index](syntax-index.md)
 * [Bibliography](bibliography.md)
index 03043f5f7376de29961ab1e13727ef60f4fb3572..9ef6d5c2bffbb4e083b8d7528aaa470eb2e05f79 100644 (file)
@@ -26,7 +26,7 @@ shells out to the system linker (`gcc` on most systems, `link.exe` on MSVC),
 so it makes sense to provide extra command line
 arguments, but this will not always be the case. In the future `rustc` may use
 LLVM directly to link native libraries, in which case `link_args` will have no
-meaning. You can achieve the same effect as the `link-args` attribute with the
+meaning. You can achieve the same effect as the `link_args` attribute with the
 `-C link-args` argument to `rustc`.
 
 It is highly recommended to *not* use this attribute, and rather use the more
@@ -71,7 +71,7 @@ Dynamic linking on Linux can be undesirable if you wish to use new library
 features on old systems or target systems which do not have the required
 dependencies for your program to run.
 
-Static linking is supported via an alternative `libc`, `musl`. You can compile
+Static linking is supported via an alternative `libc`, [`musl`](http://www.musl-libc.org). You can compile
 your own version of Rust with `musl` enabled and install it into a custom
 directory with the instructions below:
 
@@ -94,8 +94,6 @@ $ # Build libunwind.a
 $ curl -O http://llvm.org/releases/3.7.0/llvm-3.7.0.src.tar.xz
 $ tar xf llvm-3.7.0.src.tar.xz
 $ cd llvm-3.7.0.src/projects/
-llvm-3.7.0.src/projects $ curl http://llvm.org/releases/3.7.0/libcxxabi-3.7.0.src.tar.xz | tar xJf -
-llvm-3.7.0.src/projects $ mv libcxxabi-3.7.0.src libcxxabi
 llvm-3.7.0.src/projects $ curl http://llvm.org/releases/3.7.0/libunwind-3.7.0.src.tar.xz | tar xJf -
 llvm-3.7.0.src/projects $ mv libunwind-3.7.0.src libunwind
 llvm-3.7.0.src/projects $ mkdir libunwind/build
index 9659fe45857f96736cfc3d03eace596bc7a263f6..ba02053b6b8944761e85f9b9cd5feded040cebed 100644 (file)
@@ -48,7 +48,7 @@ Systems Level
 Language](http://www.cs.indiana.edu/~eholk/papers/hips2013.pdf). Early GPU work by Eric Holk.
 * [Parallel closures: a new twist on an old
   idea](https://www.usenix.org/conference/hotpar12/parallel-closures-new-twist-old-idea)
-  - not exactly about rust, but by nmatsakis
+  - not exactly about Rust, but by nmatsakis
 * [Patina: A Formalization of the Rust Programming
   Language](ftp://ftp.cs.washington.edu/tr/2015/03/UW-CSE-15-03-02.pdf). Early
   formalization of a subset of the type system, by Eric Reed.
@@ -61,8 +61,9 @@ Language](http://www.cs.indiana.edu/~eholk/papers/hips2013.pdf). Early GPU work
   Rust](http://scialex.github.io/reenix.pdf). Undergrad paper by Alex
   Light.
 * [Evaluation of performance and productivity metrics of potential
-  programming languages in the HPC environment](). Bachelor's thesis by
-  Florian Wilkens. Compares C, Go and Rust.
+  programming languages in the HPC environment]
+  (http://octarineparrot.com/assets/mrfloya-thesis-ba.pdf).
+  Bachelor's thesis by Florian Wilkens. Compares C, Go and Rust.
 * [Nom, a byte oriented, streaming, zero copy, parser combinators library
   in Rust](http://spw15.langsec.org/papers/couprie-nom.pdf). By
   Geoffroy Couprie, research for VLC.
@@ -77,4 +78,5 @@ Language](http://www.cs.indiana.edu/~eholk/papers/hips2013.pdf). Early GPU work
   Farnstrand's master's thesis.
 * [Session Types for
   Rust](http://munksgaard.me/papers/laumann-munksgaard-larsen.pdf). Philip
-  Munksgaard's master's thesis. Research for Servo.
\ No newline at end of file
+  Munksgaard's master's thesis. Research for Servo.
+* [Ownership is Theft: Experiences Building an Embedded OS in Rust - Amit Levy, et. al.](http://amitlevy.com/papers/tock-plos2015.pdf)
index dbacd405065d421ab090c3214f1e9aca8dcb613b..148c55e4b9732c96f94e9f8894c65aa2b9465505 100644 (file)
@@ -82,7 +82,7 @@ unsafe {
 with:
 
 ```text
-error: transmute called on types with different sizes: [u8; 4] (32 bits) to u64
+error: transmute called with differently sized types: [u8; 4] (32 bits) to u64
 (64 bits)
 ```
 
index b86ad47feb2e95fa1c4594b5be69793642fb7835..d9e92de8d9abcbf5b21f16166b28e5b49e562a6f 100644 (file)
@@ -204,7 +204,7 @@ borrow checker. Generally we know that such mutations won't happen in a nested f
 to check.
 
 For large, complicated programs, it becomes useful to put some things in `RefCell`s to make things
-simpler. For example, a lot of the maps in [the `ctxt` struct][ctxt] in the rust compiler internals
+simpler. For example, a lot of the maps in [the `ctxt` struct][ctxt] in the Rust compiler internals
 are inside this wrapper. These are only modified once (during creation, which is not right after
 initialization) or a couple of times in well-separated places. However, since this struct is
 pervasively used everywhere, juggling mutable and immutable pointers would be hard (perhaps
@@ -321,7 +321,7 @@ there's a lot of concurrent access happening.
 
 # Composition
 
-A common gripe when reading Rust code is with types like `Rc<RefCell<Vec<T>>>` (or even more more
+A common gripe when reading Rust code is with types like `Rc<RefCell<Vec<T>>>` (or even more
 complicated compositions of such types). It's not always clear what the composition does, or why the
 author chose one like this (and when one should be using such a composition in one's own code)
 
index 161c4ce90b2408614e80601fb45de3be3f7569dd..7d4452a4c847047d9478913034bcef43148ff17b 100644 (file)
@@ -1,9 +1,10 @@
 % Closures
 
-Rust not only has named functions, but anonymous functions as well. Anonymous
-functions that have an associated environment are called ‘closures’, because they
-close over an environment. Rust has a really great implementation of them, as
-we’ll see.
+Sometimes it is useful to wrap up a function and _free variables_ for better
+clarity and reuse. The free variables that can be used come from the
+enclosing scope and are ‘closed over’ when used in the function. From this, we
+get the name ‘closures’ and Rust provides a really great implementation of
+them, as we’ll see.
 
 # Syntax
 
@@ -34,7 +35,7 @@ assert_eq!(4, plus_two(2));
 ```
 
 You’ll notice a few things about closures that are a bit different from regular
-functions defined with `fn`. The first is that we did not need to
+named functions defined with `fn`. The first is that we did not need to
 annotate the types of arguments the closure takes or the values it returns. We
 can:
 
@@ -44,14 +45,15 @@ let plus_one = |x: i32| -> i32 { x + 1 };
 assert_eq!(2, plus_one(1));
 ```
 
-But we don’t have to. Why is this? Basically, it was chosen for ergonomic reasons.
-While specifying the full type for named functions is helpful with things like
-documentation and type inference, the types of closures are rarely documented
-since they’re anonymous, and they don’t cause the kinds of error-at-a-distance
-problems that inferring named function types can.
+But we don’t have to. Why is this? Basically, it was chosen for ergonomic
+reasons. While specifying the full type for named functions is helpful with
+things like documentation and type inference, the full type signatures of
+closures are rarely documented since they’re anonymous, and they don’t cause
+the kinds of error-at-a-distance problems that inferring named function types
+can.
 
-The second is that the syntax is similar, but a bit different. I’ve added spaces
-here for easier comparison:
+The second is that the syntax is similar, but a bit different. I’ve added
+spaces here for easier comparison:
 
 ```rust
 fn  plus_one_v1   (x: i32) -> i32 { x + 1 }
@@ -63,8 +65,8 @@ Small differences, but they’re similar.
 
 # Closures and their environment
 
-Closures are called such because they ‘close over their environment’. It
-looks like this:
+The environment for a closure can include bindings from its enclosing scope in
+addition to parameters and local bindings. It looks like this:
 
 ```rust
 let num = 5;
@@ -197,9 +199,10 @@ frame.  Without `move`, a closure may be tied to the stack frame that created
 it, while a `move` closure is self-contained. This means that you cannot
 generally return a non-`move` closure from a function, for example.
 
-But before we talk about taking and returning closures, we should talk some more
-about the way that closures are implemented. As a systems language, Rust gives
-you tons of control over what your code does, and closures are no different.
+But before we talk about taking and returning closures, we should talk some
+more about the way that closures are implemented. As a systems language, Rust
+gives you tons of control over what your code does, and closures are no
+different.
 
 # Closure implementation
 
@@ -288,9 +291,9 @@ isn’t interesting. The next part is:
 #   some_closure(1) }
 ```
 
-Because `Fn` is a trait, we can bound our generic with it. In this case, our closure
-takes a `i32` as an argument and returns an `i32`, and so the generic bound we use
-is `Fn(i32) -> i32`.
+Because `Fn` is a trait, we can bound our generic with it. In this case, our
+closure takes a `i32` as an argument and returns an `i32`, and so the generic
+bound we use is `Fn(i32) -> i32`.
 
 There’s one other key point here: because we’re bounding a generic with a
 trait, this will get monomorphized, and therefore, we’ll be doing static
@@ -411,8 +414,9 @@ fn factory() -> &(Fn(i32) -> i32) {
 ```
 
 Right. Because we have a reference, we need to give it a lifetime. But
-our `factory()` function takes no arguments, so elision doesn’t kick in
-here. What lifetime can we choose? `'static`:
+our `factory()` function takes no arguments, so
+[elision](lifetimes.html#lifetime-elision) doesn’t kick in here. Then what
+choices do we have? Try `'static`:
 
 ```rust,ignore
 fn factory() -> &'static (Fn(i32) -> i32) {
@@ -432,7 +436,7 @@ But we get another error:
 ```text
 error: mismatched types:
  expected `&'static core::ops::Fn(i32) -> i32`,
-    found `[closure <anon>:7:9: 7:20]`
+    found `[closure@<anon>:7:9: 7:20]`
 (expected &-ptr,
     found closure) [E0308]
          |x| x + num
@@ -441,21 +445,17 @@ error: mismatched types:
 ```
 
 This error is letting us know that we don’t have a `&'static Fn(i32) -> i32`,
-we have a `[closure <anon>:7:9: 7:20]`. Wait, what?
+we have a `[closure@<anon>:7:9: 7:20]`. Wait, what?
 
 Because each closure generates its own environment `struct` and implementation
 of `Fn` and friends, these types are anonymous. They exist just solely for
-this closure. So Rust shows them as `closure <anon>`, rather than some
+this closure. So Rust shows them as `closure@<anon>`, rather than some
 autogenerated name.
 
-But why doesn’t our closure implement `&'static Fn`? Well, as we discussed before,
-closures borrow their environment. And in this case, our environment is based
-on a stack-allocated `5`, the `num` variable binding. So the borrow has a lifetime
-of the stack frame. So if we returned this closure, the function call would be
-over, the stack frame would go away, and our closure is capturing an environment
-of garbage memory!
-
-So what to do? This _almost_ works:
+The error also points out that the return type is expected to be a reference,
+but what we are trying to return is not. Further, we cannot directly assign a
+`'static` lifetime to an object. So we'll take a different approach and return
+a ‘trait object’ by `Box`ing up the `Fn`. This _almost_ works:
 
 ```rust,ignore
 fn factory() -> Box<Fn(i32) -> i32> {
@@ -471,7 +471,7 @@ assert_eq!(6, answer);
 # }
 ```
 
-We use a trait object, by `Box`ing up the `Fn`. There’s just one last problem:
+There’s just one last problem:
 
 ```text
 error: closure may outlive the current function, but it borrows `num`,
@@ -480,8 +480,12 @@ Box::new(|x| x + num)
          ^~~~~~~~~~~
 ```
 
-We still have a reference to the parent stack frame. With one last fix, we can
-make this work:
+Well, as we discussed before, closures borrow their environment. And in this
+case, our environment is based on a stack-allocated `5`, the `num` variable
+binding. So the borrow has a lifetime of the stack frame. So if we returned
+this closure, the function call would be over, the stack frame would go away,
+and our closure is capturing an environment of garbage memory! With one last
+fix, we can make this work:
 
 ```rust
 fn factory() -> Box<Fn(i32) -> i32> {
index ffa8be5ac084b224b53c033b2f2c20c2a01246ba..e1c982511170993fd137957be85580b417f4d1b8 100644 (file)
@@ -170,13 +170,25 @@ starting point for an improved quasiquote as an ordinary plugin library.
 
 Plugins can extend [Rust's lint
 infrastructure](../reference.html#lint-check-attributes) with additional checks for
-code style, safety, etc. You can see
-[`src/test/auxiliary/lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/auxiliary/lint_plugin_test.rs)
-for a full example, the core of which is reproduced here:
+code style, safety, etc. Now let's write a plugin [`lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/auxiliary/lint_plugin_test.rs)
+that warns about any item named `lintme`.
 
 ```ignore
-declare_lint!(TEST_LINT, Warn,
-              "Warn about items named 'lintme'");
+#![feature(plugin_registrar)]
+#![feature(box_syntax, rustc_private)]
+
+extern crate syntax;
+
+// Load rustc as a plugin to get macros
+#[macro_use]
+extern crate rustc;
+
+use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass,
+                  EarlyLintPassObject, LintArray};
+use rustc::plugin::Registry;
+use syntax::ast;
+
+declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
 
 struct Pass;
 
@@ -184,9 +196,11 @@ impl LintPass for Pass {
     fn get_lints(&self) -> LintArray {
         lint_array!(TEST_LINT)
     }
+}
 
-    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
-        if it.ident.name == "lintme" {
+impl EarlyLintPass for Pass {
+    fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
+        if it.ident.name.as_str() == "lintme" {
             cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'");
         }
     }
@@ -194,7 +208,7 @@ impl LintPass for Pass {
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_lint_pass(box Pass as LintPassObject);
+    reg.register_early_lint_pass(box Pass as EarlyLintPassObject);
 }
 ```
 
index e00fe75013e29cf31fac8e2bb1f8d1abade5806d..7b3f13a3ed2235b9363475e7c72c1baa751b8b7b 100644 (file)
@@ -26,8 +26,8 @@ to help us make sense of code that can possibly be concurrent.
 ### `Send`
 
 The first trait we're going to talk about is
-[`Send`](../std/marker/trait.Send.html). When a type `T` implements `Send`, it indicates
-to the compiler that something of this type is able to have ownership transferred
+[`Send`](../std/marker/trait.Send.html). When a type `T` implements `Send`, it
+indicates that something of this type is able to have ownership transferred
 safely between threads.
 
 This is important to enforce certain restrictions. For example, if we have a
@@ -35,20 +35,28 @@ channel connecting two threads, we would want to be able to send some data
 down the channel and to the other thread. Therefore, we'd ensure that `Send` was
 implemented for that type.
 
-In the opposite way, if we were wrapping a library with FFI that isn't
+In the opposite way, if we were wrapping a library with [FFI][ffi] that isn't
 threadsafe, we wouldn't want to implement `Send`, and so the compiler will help
 us enforce that it can't leave the current thread.
 
+[ffi]: ffi.html
+
 ### `Sync`
 
 The second of these traits is called [`Sync`](../std/marker/trait.Sync.html).
-When a type `T` implements `Sync`, it indicates to the compiler that something
+When a type `T` implements `Sync`, it indicates that something
 of this type has no possibility of introducing memory unsafety when used from
-multiple threads concurrently.
-
-For example, sharing immutable data with an atomic reference count is
-threadsafe. Rust provides a type like this, `Arc<T>`, and it implements `Sync`,
-so it is safe to share between threads.
+multiple threads concurrently through shared references. This implies that
+types which don't have [interior mutability](mutability.html) are inherently
+`Sync`, which includes simple primitive types (like `u8`) and aggregate types
+containing them.
+
+For sharing references across threads, Rust provides a wrapper type called
+`Arc<T>`. `Arc<T>` implements `Send` and `Sync` if and only if `T` implements
+both `Send` and `Sync`. For example, an object of type `Arc<RefCell<U>>` cannot
+be transferred across threads because
+[`RefCell`](choosing-your-guarantees.html#refcellt) does not implement
+`Sync`, consequently `Arc<RefCell<U>>` would not implement `Send`.
 
 These two traits allow you to use the type system to make strong guarantees
 about the properties of your code under concurrency. Before we demonstrate
@@ -70,7 +78,7 @@ fn main() {
 }
 ```
 
-The `thread::spawn()` method accepts a closure, which is executed in a
+The `thread::spawn()` method accepts a [closure](closures.html), which is executed in a
 new thread. It returns a handle to the thread, that can be used to
 wait for the child thread to finish and extract its result:
 
@@ -142,7 +150,7 @@ owners!
 So, we need some type that lets us have more than one reference to a value and
 that we can share between threads, that is it must implement `Sync`.
 
-We'll use `Arc<T>`, rust's standard atomic reference count type, which
+We'll use `Arc<T>`, Rust's standard atomic reference count type, which
 wraps a value up with some extra runtime bookkeeping which allows us to
 share the ownership of the value between multiple references at the same time.
 
@@ -189,7 +197,7 @@ our value if it's immutable, but we want to be able to mutate it, so we need
 something else to persuade the borrow checker we know what we're doing.
 
 It looks like we need some type that allows us to safely mutate a shared value,
-for example a type that that can ensure only one thread at a time is able to
+for example a type that can ensure only one thread at a time is able to
 mutate the value inside it at any one time.
 
 For that, we can use the `Mutex<T>` type!
@@ -215,29 +223,18 @@ fn main() {
 }
 ```
 
+Note that the value of `i` is bound (copied) to the closure and not shared
+among the threads.
 
-If we'd tried to use `Mutex<T>` without wrapping it in an `Arc<T>` we would have
-seen another error like:
-
-```text
-error: the trait `core::marker::Send` is not implemented for the type `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` [E0277]
- thread::spawn(move || {
-                  ^~~~~~~~~~~~~
-note: `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` cannot be sent between threads safely
- thread::spawn(move || {
-                  ^~~~~~~~~~~~~
-```
-
-You see, [`Mutex`](../std/sync/struct.Mutex.html) has a
-[`lock`](../std/sync/struct.Mutex.html#method.lock)
-method which has this signature:
+Also note that [`lock`](../std/sync/struct.Mutex.html#method.lock) method of
+[`Mutex`](../std/sync/struct.Mutex.html) has this signature:
 
 ```ignore
 fn lock(&self) -> LockResult<MutexGuard<T>>
 ```
 
-and because `Send` is not implemented for `MutexGuard<T>`, we couldn't have
-transferred the guard across thread boundaries on it's own.
+and because `Send` is not implemented for `MutexGuard<T>`, the guard cannot
+cross thread boundaries, ensuring thread-locality of lock acquire and release.
 
 Let's examine the body of the thread more closely:
 
@@ -317,22 +314,24 @@ use std::sync::mpsc;
 fn main() {
     let (tx, rx) = mpsc::channel();
 
-    for _ in 0..10 {
+    for i in 0..10 {
         let tx = tx.clone();
 
         thread::spawn(move || {
-            let answer = 42;
+            let answer = i * i;
 
             tx.send(answer);
         });
     }
 
-   rx.recv().ok().expect("Could not receive answer");
+    for _ in 0..10 {
+        println!("{}", rx.recv().unwrap());
+    }
 }
 ```
 
-A `u32` is `Send` because we can make a copy. So we create a thread, ask it to calculate
-the answer, and then it `send()`s us the answer over the channel.
+Here we create 10 threads, asking each to calculate the square of a number (`i`
+at the time of `spawn()`), and then `send()` back the answer over the channel.
 
 
 ## Panics
index a944b852d249fcc46f84658f9977d7b30e68861b..a6ff75db89b88ddccbefe9f1b315df47d9e14240 100644 (file)
@@ -34,7 +34,7 @@ These can nest arbitrarily:
 As for how to enable or disable these switches, if you’re using Cargo,
 they get set in the [`[features]` section][features] of your `Cargo.toml`:
 
-[features]: http://doc.crates.io/manifest.html#the-%5Bfeatures%5D-section
+[features]: http://doc.crates.io/manifest.html#the-features-section
 
 ```toml
 [features]
index 1c5115117cb17f7b4a4afa7159895f2d09b741f0..4a4648c7b563f4fe4bbcab815e54dbc9da7d6eb5 100644 (file)
@@ -563,8 +563,8 @@ What's going on here?
 First, both `extern crate` and `use` allow renaming the thing that is being
 imported. So the crate is still called "phrases", but here we will refer
 to it as "sayings". Similarly, the first `use` statement pulls in the
-`japanese::farewells` module from the crate, but makes it available as
-`jp_farewells` as opposed to simply `farewells`. This can help to avoid
+`japanese::greetings` module from the crate, but makes it available as
+`ja_greetings` as opposed to simply `greetings`. This can help to avoid
 ambiguity when importing similarly-named items from different places.
 
 The second `use` statement uses a star glob to bring in _all_ symbols from the
@@ -576,11 +576,13 @@ The third `use` statement bears more explanation. It's using "brace expansion"
 globbing to compress three `use` statements into one (this sort of syntax
 may be familiar if you've written Linux shell scripts before). The
 uncompressed form of this statement would be:
+
 ```rust,ignore
 use sayings::english;
 use sayings::english::greetings as en_greetings;
 use sayings::english::farewells as en_farewells;
 ```
+
 As you can see, the curly brackets compress `use` statements for several items
 under the same path, and in this context `self` just refers back to that path.
 Note: The curly brackets cannot be nested or mixed with star globbing.
diff --git a/src/doc/trpl/custom-allocators.md b/src/doc/trpl/custom-allocators.md
new file mode 100644 (file)
index 0000000..c38d0dd
--- /dev/null
@@ -0,0 +1,170 @@
+% Custom Allocators
+
+Allocating memory isn't always the easiest thing to do, and while Rust generally
+takes care of this by default it often becomes necessary to customize how
+allocation occurs. The compiler and standard library currently allow switching
+out the default global allocator in use at compile time. The design is currently
+spelled out in [RFC 1183][rfc] but this will walk you through how to get your
+own allocator up and running.
+
+[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1183-swap-out-jemalloc.md
+
+# Default Allocator
+
+The compiler currently ships two default allocators: `alloc_system` and
+`alloc_jemalloc` (some targets don't have jemalloc, however). These allocators
+are just normal Rust crates and contain an implementation of the routines to
+allocate and deallocate memory. The standard library is not compiled assuming
+either one, and the compiler will decide which allocator is in use at
+compile-time depending on the type of output artifact being produced.
+
+Binaries generated by the compiler will use `alloc_jemalloc` by default (where
+available). In this situation the compiler "controls the world" in the sense of
+it has power over the final link. Primarily this means that the allocator
+decision can be left up the compiler.
+
+Dynamic and static libraries, however, will use `alloc_system` by default. Here
+Rust is typically a 'guest' in another application or another world where it
+cannot authoritatively decide what allocator is in use. As a result it resorts
+back to the standard APIs (e.g. `malloc` and `free`) for acquiring and releasing
+memory.
+
+# Switching Allocators
+
+Although the compiler's default choices may work most of the time, it's often
+necessary to tweak certain aspects. Overriding the compiler's decision about
+which allocator is in use is done simply by linking to the desired allocator:
+
+```rust,no_run
+#![feature(alloc_system)]
+
+extern crate alloc_system;
+
+fn main() {
+    let a = Box::new(4); // allocates from the system allocator
+    println!("{}", a);
+}
+```
+
+In this example the binary generated will not link to jemalloc by default but
+instead use the system allocator. Conversely to generate a dynamic library which
+uses jemalloc by default one would write:
+
+```rust,ignore
+#![feature(alloc_jemalloc)]
+#![crate_type = "dylib"]
+
+extern crate alloc_jemalloc;
+
+pub fn foo() {
+    let a = Box::new(4); // allocates from jemalloc
+    println!("{}", a);
+}
+# fn main() {}
+```
+
+# Writing a custom allocator
+
+Sometimes even the choices of jemalloc vs the system allocator aren't enough and
+an entirely new custom allocator is required. In this you'll write your own
+crate which implements the allocator API (e.g. the same as `alloc_system` or
+`alloc_jemalloc`). As an example, let's take a look at a simplified and
+annotated version of `alloc_system`
+
+```rust,no_run
+# // only needed for rustdoc --test down below
+# #![feature(lang_items)]
+// The compiler needs to be instructed that this crate is an allocator in order
+// to realize that when this is linked in another allocator like jemalloc should
+// not be linked in
+#![feature(allocator)]
+#![allocator]
+
+// Allocators are not allowed to depend on the standard library which in turn
+// requires an allocator in order to avoid circular dependencies. This crate,
+// however, can use all of libcore.
+#![feature(no_std)]
+#![no_std]
+
+// Let's give a unique name to our custom allocator
+#![crate_name = "my_allocator"]
+#![crate_type = "rlib"]
+
+// Our system allocator will use the in-tree libc crate for FFI bindings. Note
+// that currently the external (crates.io) libc cannot be used because it links
+// to the standard library (e.g. `#![no_std]` isn't stable yet), so that's why
+// this specifically requires the in-tree version.
+#![feature(libc)]
+extern crate libc;
+
+// Listed below are the five allocation functions currently required by custom
+// allocators. Their signatures and symbol names are not currently typechecked
+// by the compiler, but this is a future extension and are required to match
+// what is found below.
+//
+// Note that the standard `malloc` and `realloc` functions do not provide a way
+// to communicate alignment so this implementation would need to be improved
+// with respect to alignment in that aspect.
+
+#[no_mangle]
+pub extern fn __rust_allocate(size: usize, _align: usize) -> *mut u8 {
+    unsafe { libc::malloc(size as libc::size_t) as *mut u8 }
+}
+
+#[no_mangle]
+pub extern fn __rust_deallocate(ptr: *mut u8, _old_size: usize, _align: usize) {
+    unsafe { libc::free(ptr as *mut libc::c_void) }
+}
+
+#[no_mangle]
+pub extern fn __rust_reallocate(ptr: *mut u8, _old_size: usize, size: usize,
+                                _align: usize) -> *mut u8 {
+    unsafe {
+        libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
+    }
+}
+
+#[no_mangle]
+pub extern fn __rust_reallocate_inplace(_ptr: *mut u8, old_size: usize,
+                                        _size: usize, _align: usize) -> usize {
+    old_size // this api is not supported by libc
+}
+
+#[no_mangle]
+pub extern fn __rust_usable_size(size: usize, _align: usize) -> usize {
+    size
+}
+
+# // just needed to get rustdoc to test this
+# fn main() {}
+# #[lang = "panic_fmt"] fn panic_fmt() {}
+# #[lang = "eh_personality"] fn eh_personality() {}
+# #[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {}
+```
+
+After we compile this crate, it can be used as follows:
+
+```rust,ignore
+extern crate my_allocator;
+
+fn main() {
+    let a = Box::new(8); // allocates memory via our custom allocator crate
+    println!("{}", a);
+}
+```
+
+# Custom allocator limitations
+
+There are a few restrictions when working with custom allocators which may cause
+compiler errors:
+
+* Any one artifact may only be linked to at most one allocator. Binaries,
+  dylibs, and staticlibs must link to exactly one allocator, and if none have
+  been explicitly chosen the compiler will choose one. On the other hand rlibs
+  do not need to link to an allocator (but still can).
+
+* A consumer of an allocator is tagged with `#![needs_allocator]` (e.g. the
+  `liballoc` crate currently) and an `#[allocator]` crate cannot transitively
+  depend on a crate which needs an allocator (e.g. circular dependencies are not
+  allowed). This basically means that allocators must restrict themselves to
+  libcore currently.
index 9539cd3447cb9f023bec1813c475871ea9da438b..e81ae4648ad4323c9daa1f0631b25bd7c4dc62d1 100644 (file)
@@ -13,7 +13,7 @@ Hoare in 1985.
 > dining room, furnished with a circular table, surrounded by five chairs, each
 > labelled by the name of the philosopher who was to sit in it. They sat
 > anticlockwise around the table. To the left of each philosopher there was
-> laid a golden fork, and in the centre stood a large bowl of spaghetti, which
+> laid a golden fork, and in the center stood a large bowl of spaghetti, which
 > was constantly replenished. A philosopher was expected to spend most of
 > their time thinking; but when they felt hungry, they went to the dining
 > room, sat down in their own chair, picked up their own fork on their left,
@@ -45,7 +45,7 @@ Now, let’s imagine this sequence of events:
 6. ... ? All the forks are taken, but nobody can eat!
 
 There are different ways to solve this problem. We’ll get to our solution in
-the tutorial itself. For now, let’s get started modelling the problem itself.
+the tutorial itself. For now, let’s get started modeling the problem itself.
 We’ll start with the philosophers:
 
 ```rust
@@ -434,7 +434,7 @@ ownership of the values it’s capturing. Primarily, the `p` variable of the
 
 Inside the thread, all we do is call `eat()` on `p`. Also note that the call to `thread::spawn` lacks a trailing semicolon, making this an expression. This distinction is important, yielding the correct return value. For more details, read [Expressions vs. Statements][es].
 
-[es]: functions.html#expressions-vs.-statements
+[es]: functions.html#expressions-vs-statements
 
 ```rust,ignore
 }).collect();
@@ -512,6 +512,7 @@ impl Philosopher {
 
     fn eat(&self, table: &Table) {
         let _left = table.forks[self.left].lock().unwrap();
+        thread::sleep_ms(150);
         let _right = table.forks[self.right].lock().unwrap();
 
         println!("{} is eating.", self.name);
@@ -597,6 +598,7 @@ We now need to construct those `left` and `right` values, so we add them to
 ```rust,ignore
 fn eat(&self, table: &Table) {
     let _left = table.forks[self.left].lock().unwrap();
+    thread::sleep_ms(150);
     let _right = table.forks[self.right].lock().unwrap();
 
     println!("{} is eating.", self.name);
@@ -607,11 +609,14 @@ fn eat(&self, table: &Table) {
 }
 ```
 
-We have two new lines. We’ve also added an argument, `table`. We access the
+We have three new lines. We’ve added an argument, `table`. We access the
 `Table`’s list of forks, and then use `self.left` and `self.right` to access
 the fork at that particular index. That gives us access to the `Mutex` at that
 index, and we call `lock()` on it. If the mutex is currently being accessed by
-someone else, we’ll block until it becomes available.
+someone else, we’ll block until it becomes available. We have also a call to
+`thread::sleep_ms` between the moment first fork is picked and the moment the
+second forked is picked, as the process  of picking up the fork is not
+immediate.
 
 The call to `lock()` might fail, and if it does, we want to crash. In this
 case, the error that could happen is that the mutex is [‘poisoned’][poison],
@@ -660,7 +665,9 @@ We need to pass in our `left` and `right` values to the constructors for our
 you look at the pattern, it’s all consistent until the very end. Monsieur
 Foucault should have `4, 0` as arguments, but instead, has `0, 4`. This is what
 prevents deadlock, actually: one of our philosophers is left handed! This is
-one way to solve the problem, and in my opinion, it’s the simplest.
+one way to solve the problem, and in my opinion, it’s the simplest. If you
+change the order of the parameters, you will be able to observe the deadlock
+taking place.
 
 ```rust,ignore
 let handles: Vec<_> = philosophers.into_iter().map(|p| {
index 0a471beb43914fdd84967f80cefd6b4c58a793ec..e101d4bc0d4dc47b748e3fc24ef071ff2b7bd482 100644 (file)
@@ -45,7 +45,7 @@ Rust keeps track of these comments, and uses them when generating
 documentation. This is important when documenting things like enums:
 
 ```rust
-/// The `Option` type. See [the module level documentation](../) for more.
+/// The `Option` type. See [the module level documentation](index.html) for more.
 enum Option<T> {
     /// No value
     None,
@@ -57,7 +57,7 @@ enum Option<T> {
 The above works, but this does not:
 
 ```rust,ignore
-/// The `Option` type. See [the module level documentation](../) for more.
+/// The `Option` type. See [the module level documentation](index.html) for more.
 enum Option<T> {
     None, /// No value
     Some(T), /// Some value `T`
@@ -73,7 +73,7 @@ hello.rs:4 }
 ```
 
 This [unfortunate error](https://github.com/rust-lang/rust/issues/22547) is
-correct: documentation comments apply to the thing after them, and there's 
+correct: documentation comments apply to the thing after them, and there's
 nothing after that last comment.
 
 [rc-new]: https://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.new
@@ -213,7 +213,7 @@ Let's discuss our sample example documentation:
 ```
 
 You'll notice that you don't need a `fn main()` or anything here. `rustdoc` will
-automatically add a main() wrapper around your code, and in the right place.
+automatically add a `main()` wrapper around your code, and in the right place.
 For example:
 
 ```rust
@@ -234,7 +234,7 @@ fn main() {
 }
 ```
 
-Here's the full algorithm rustdoc uses to postprocess examples:
+Here's the full algorithm rustdoc uses to preprocess examples:
 
 1. Any leading `#![foo]` attributes are left intact as crate attributes.
 2. Some common `allow` attributes are inserted, including
@@ -269,45 +269,21 @@ documentation comment, I need to add a little function definition below
 it. At the same time, it's just there to satisfy the compiler, so hiding
 it makes the example more clear. You can use this technique to explain
 longer examples in detail, while still preserving the testability of your
-documentation. For example, this code:
-
-```rust
-let x = 5;
-let y = 6;
-println!("{}", x + y);
-```
-
-Here's an explanation, rendered:
+documentation.
 
-First, we set `x` to five:
+For example, imagine that we wanted to document this code:
 
 ```rust
 let x = 5;
-# let y = 6;
-# println!("{}", x + y);
-```
-
-Next, we set `y` to six:
-
-```rust
-# let x = 5;
 let y = 6;
-# println!("{}", x + y);
-```
-
-Finally, we print the sum of `x` and `y`:
-
-```rust
-# let x = 5;
-# let y = 6;
 println!("{}", x + y);
 ```
 
-Here's the same explanation, in raw text:
+We might want the documentation to end up looking like this:
 
 > First, we set `x` to five:
 >
-> ```text
+> ```rust
 > let x = 5;
 > # let y = 6;
 > # println!("{}", x + y);
@@ -315,7 +291,7 @@ Here's the same explanation, in raw text:
 >
 > Next, we set `y` to six:
 >
-> ```text
+> ```rust
 > # let x = 5;
 > let y = 6;
 > # println!("{}", x + y);
@@ -323,12 +299,42 @@ Here's the same explanation, in raw text:
 >
 > Finally, we print the sum of `x` and `y`:
 >
-> ```text
+> ```rust
 > # let x = 5;
 > # let y = 6;
 > println!("{}", x + y);
 > ```
 
+To keep each code block testable, we want the whole program in each block, but
+we don't want the reader to see every line every time.  Here's what we put in
+our source code:
+
+```text
+    First, we set `x` to five:
+
+    ```text
+    let x = 5;
+    # let y = 6;
+    # println!("{}", x + y);
+    ```
+
+    Next, we set `y` to six:
+
+    ```text
+    # let x = 5;
+    let y = 6;
+    # println!("{}", x + y);
+    ```
+
+    Finally, we print the sum of `x` and `y`:
+
+    ```text
+    # let x = 5;
+    # let y = 6;
+    println!("{}", x + y);
+    ```
+```
+
 By repeating all parts of the example, you can ensure that your example still
 compiles, while only showing the parts that are relevant to that part of your
 explanation.
@@ -369,7 +375,7 @@ things, so they don’t show up in the output.
 
 ### Running documentation tests
 
-To run the tests, either
+To run the tests, either:
 
 ```bash
 $ rustdoc --test path/to/my/crate/root.rs
@@ -494,7 +500,8 @@ This `%` line needs to be the very first line of the file.
 
 ## `doc` attributes
 
-At a deeper level, documentation comments are sugar for documentation attributes:
+At a deeper level, documentation comments are syntactic sugar for documentation
+attributes:
 
 ```rust
 /// this
@@ -509,7 +516,7 @@ are the same, as are these:
 ```rust
 //! this
 
-#![doc="/// this"]
+#![doc="this"]
 ```
 
 You won't often see this attribute used for writing documentation, but it
@@ -525,7 +532,7 @@ extern crate foo;
 pub use foo::bar;
 ```
 
-This will create documentation for bar both inside the documentation for the
+This will create documentation for `bar` both inside the documentation for the
 crate `foo`, as well as the documentation for your crate. It will use the same
 documentation in both places.
 
@@ -538,6 +545,38 @@ extern crate foo;
 pub use foo::bar;
 ```
 
+## Missing documentation
+
+Sometimes you want to make sure that every single public thing in your project
+is documented, especially when you are working on a library. Rust allows you to
+to generate warnings or errors, when an item is missing documentation.
+To generate warnings you use `warn`:
+
+```rust
+#![warn(missing_docs)]
+```
+
+And to generate errors you use `deny`:
+
+```rust,ignore
+#![deny(missing_docs)]
+```
+
+There are cases where you want to disable these warnings/errors to explicitly
+leave something undocumented. This is done by using `allow`:
+
+```rust
+#[allow(missing_docs)]
+struct Undocumented;
+```
+
+You might even want to hide items from the documentation completely:
+
+```rust
+#[doc(hidden)]
+struct Hidden;
+```
+
 ### Controlling HTML
 
 You can control a few aspects of the HTML that `rustdoc` generates through the
index 673dc950ecce4187f0aaa39547747d7c99b6c76d..56dfa17b4e3f21c795c26a7281636de122187adb 100644 (file)
@@ -87,6 +87,8 @@ thread '<main>' panicked at 'Invalid number: 11', src/bin/panic-simple.rs:5
 Here's another example that is slightly less contrived. A program that accepts
 an integer as an argument, doubles it and prints it.
 
+<span id="code-unwrap-double"></span>
+
 ```rust,should_panic
 use std::env;
 
@@ -120,10 +122,9 @@ It would be better if we just showed the code for unwrapping because it is so
 simple, but to do that, we will first need to explore the `Option` and `Result`
 types. Both of these types have a method called `unwrap` defined on them.
 
-## The `Option` type
+### The `Option` type
 
-The `Option` type is
-[defined in the standard library][1]: 
+The `Option` type is [defined in the standard library][5]:
 
 ```rust
 enum Option<T> {
@@ -138,6 +139,8 @@ system is an important concept because it will cause the compiler to force the
 programmer to handle that absence. Let's take a look at an example that tries
 to find a character in a string:
 
+<span id="code-option-ex-string-find"></span>
+
 ```rust
 // Searches `haystack` for the Unicode character `needle`. If one is found, the
 // byte offset of the character is returned. Otherwise, `None` is returned.
@@ -151,7 +154,7 @@ fn find(haystack: &str, needle: char) -> Option<usize> {
 }
 ```
 
-Notice that when this function finds a matching character, it doen't just
+Notice that when this function finds a matching character, it doesn't just
 return the `offset`. Instead, it returns `Some(offset)`. `Some` is a variant or
 a *value constructor* for the `Option` type. You can think of it as a function
 with the type `fn<T>(value: T) -> Option<T>`. Correspondingly, `None` is also a
@@ -179,10 +182,12 @@ analysis is the only way to get at the value stored inside an `Option<T>`. This
 means that you, as the programmer, must handle the case when an `Option<T>` is
 `None` instead of `Some(t)`.
 
-But wait, what about `unwrap` used in [`unwrap-double`](#code-unwrap-double)?
+But wait, what about `unwrap`,which we used [`previously`](#code-unwrap-double)?
 There was no case analysis there! Instead, the case analysis was put inside the
 `unwrap` method for you. You could define it yourself if you want:
 
+<span id="code-option-def-unwrap"></span>
+
 ```rust
 enum Option<T> {
     None,
@@ -206,7 +211,7 @@ that makes `unwrap` ergonomic to use. Unfortunately, that `panic!` means that
 
 ### Composing `Option<T>` values
 
-In [`option-ex-string-find`](#code-option-ex-string-find-2)
+In an [example from before](#code-option-ex-string-find),
 we saw how to use `find` to discover the extension in a file name. Of course,
 not all file names have a `.` in them, so it's possible that the file name has
 no extension. This *possibility of absence* is encoded into the types using
@@ -220,7 +225,7 @@ sense to put it into a function:
 ```rust
 # fn find(_: &str, _: char) -> Option<usize> { None }
 // Returns the extension of the given file name, where the extension is defined
-// as all characters proceding the first `.`.
+// as all characters proceeding the first `.`.
 // If `file_name` has no `.`, then `None` is returned.
 fn extension_explicit(file_name: &str) -> Option<&str> {
     match find(file_name, '.') {
@@ -248,6 +253,8 @@ option is `None`, in which case, just return `None`.
 Rust has parametric polymorphism, so it is very easy to define a combinator
 that abstracts this pattern:
 
+<span id="code-option-map"></span>
+
 ```rust
 fn map<F, T, A>(option: Option<T>, f: F) -> Option<A> where F: FnOnce(T) -> A {
     match option {
@@ -265,18 +272,18 @@ to get rid of the case analysis:
 ```rust
 # fn find(_: &str, _: char) -> Option<usize> { None }
 // Returns the extension of the given file name, where the extension is defined
-// as all characters proceding the first `.`.
+// as all characters proceeding the first `.`.
 // If `file_name` has no `.`, then `None` is returned.
 fn extension(file_name: &str) -> Option<&str> {
     find(file_name, '.').map(|i| &file_name[i+1..])
 }
 ```
 
-One other pattern that we find is very common is assigning a default value to
-the case when an `Option` value is `None`. For example, maybe your program
-assumes that the extension of a file is `rs` even if none is present. As you
-might imagine, the case analysis for this is not specific to file
-extensions - it can work with any `Option<T>`:
+One other pattern we commonly find is assigning a default value to the case
+when an `Option` value is `None`. For example, maybe your program assumes that
+the extension of a file is `rs` even if none is present. As you might imagine,
+the case analysis for this is not specific to file extensions - it can work
+with any `Option<T>`:
 
 ```rust
 fn unwrap_or<T>(option: Option<T>, default: T) -> T {
@@ -387,6 +394,8 @@ remove choices because they will panic if `Option<T>` is `None`.
 The `Result` type is also
 [defined in the standard library][6]:
 
+<span id="code-result-def"></span>
+
 ```rust
 enum Result<T, E> {
     Ok(T),
@@ -553,7 +562,7 @@ combinators that affect only the error type, such as
 ### The `Result` type alias idiom
 
 In the standard library, you may frequently see types like
-`Result<i32>`. But wait, [we defined `Result`](#code-result-def-1) to
+`Result<i32>`. But wait, [we defined `Result`](#code-result-def) to
 have two type parameters. How can we get away with only specifying
 one? The key is to define a `Result` type alias that *fixes* one of
 the type parameters to a particular type. Usually the fixed type is
@@ -663,6 +672,8 @@ with both an `Option` and a `Result`, the solution is *usually* to convert the
 (from `env::args()`) means the user didn't invoke the program correctly. We
 could just use a `String` to describe the error. Let's try:
 
+<span id="code-error-double-string"></span>
+
 ```rust
 use std::env;
 
@@ -744,7 +755,7 @@ fn main() {
 (N.B. The `AsRef<Path>` is used because those are the
 [same bounds used on
 `std::fs::File::open`](../std/fs/struct.File.html#method.open).
-This makes it ergnomic to use any kind of string as a file path.)
+This makes it ergonomic to use any kind of string as a file path.)
 
 There are three different errors that can occur here:
 
@@ -829,7 +840,7 @@ example, the very last call to `map` multiplies the `Ok(...)` value (which is
 an `i32`) by `2`. If an error had occurred before that point, this operation
 would have been skipped because of how `map` is defined.
 
-`map_err` is the trick the makes all of this work. `map_err` is just like
+`map_err` is the trick that makes all of this work. `map_err` is just like
 `map`, except it applies a function to the `Err(...)` value of a `Result`. In
 this case, we want to convert all of our errors to one type: `String`. Since
 both `io::Error` and `num::ParseIntError` implement `ToString`, we can call the
@@ -895,6 +906,8 @@ seen above.
 
 Here is a simplified definition of a `try!` macro:
 
+<span id="code-try-def-simple"></span>
+
 ```rust
 macro_rules! try {
     ($e:expr) => (match $e {
@@ -1155,6 +1168,8 @@ The `std::convert::From` trait is
 [defined in the standard
 library](../std/convert/trait.From.html):
 
+<span id="code-from-def"></span>
+
 ```rust
 trait From<T> {
     fn from(T) -> Self;
@@ -1208,7 +1223,7 @@ let err2: Box<Error> = From::from(parse_err);
 
 There is a really important pattern to recognize here. Both `err1` and `err2`
 have the *same type*. This is because they are existentially quantified types,
-or trait objects. In particularly, their underlying type is *erased* from the
+or trait objects. In particular, their underlying type is *erased* from the
 compiler's knowledge, so it truly sees `err1` and `err2` as exactly the same.
 Additionally, we constructed `err1` and `err2` using precisely the same
 function call: `From::from`. This is because `From::from` is overloaded on both
@@ -1232,9 +1247,11 @@ macro_rules! try {
 }
 ```
 
-This is not it's real definition. It's real definition is
+This is not its real definition. Its real definition is
 [in the standard library](../std/macro.try!.html):
 
+<span id="code-try-def"></span>
+
 ```rust
 macro_rules! try {
     ($e:expr) => (match $e {
@@ -1267,7 +1284,7 @@ fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, String> {
 
 Earlier, we promised that we could get rid of the `map_err` calls. Indeed, all
 we have to do is pick a type that `From` works with. As we saw in the previous
-section, `From` has an impl that let's it convert any error type into a
+section, `From` has an impl that lets it convert any error type into a
 `Box<Error>`:
 
 ```rust
@@ -1498,7 +1515,7 @@ and [`rustc-serialize`](https://crates.io/crates/rustc-serialize) crates.
 
 We're not going to spend a lot of time on setting up a project with
 Cargo because it is already covered well in [the Cargo
-chapter](../book/hello-cargo) and [Cargo's documentation][14].
+chapter](../book/hello-cargo.html) and [Cargo's documentation][14].
 
 To get started from scratch, run `cargo new --bin city-pop` and make sure your
 `Cargo.toml` looks something like this:
@@ -1528,14 +1545,14 @@ cargo build --release
 
 ## Argument parsing
 
-Let's get argument parsing out of the way. we won't go into too much
+Let's get argument parsing out of the way. We won't go into too much
 detail on Getopts, but there is [some good documentation][15]
 describing it. The short story is that Getopts generates an argument
 parser and a help message from a vector of options (The fact that it
 is a vector is hidden behind a struct and a set of methods). Once the
 parsing is done, we can decode the program arguments into a Rust
 struct. From there, we can get information about the flags, for
-instance, wether they were passed in, and what arguments they
+instance, whether they were passed in, and what arguments they
 had. Here's our program with the appropriate `extern crate`
 statements, and the basic argument setup for Getopts:
 
@@ -1556,7 +1573,7 @@ fn main() {
 
     let mut opts = Options::new();
     opts.optflag("h", "help", "Show this usage message.");
-    
+
     let matches = match opts.parse(&args[1..]) {
         Ok(m)  => { m }
        Err(e) => { panic!(e.to_string()) }
@@ -1567,7 +1584,7 @@ fn main() {
     }
     let data_path = args[1].clone();
     let city = args[2].clone();
-       
+
        // Do stuff with information
 }
 ```
@@ -1577,7 +1594,7 @@ then store the first one, knowing that it is our program's name. Once
 that's done, we set up our argument flags, in this case a simplistic
 help message flag. Once we have the argument flags set up, we use
 `Options.parse` to parse the argument vector (starting from index one,
-becouse index 0 is the program name). If this was successful, we
+because index 0 is the program name). If this was successful, we
 assign matches to the parsed object, if not, we panic. Once past that,
 we test if the user passed in the help flag, and if so print the usage
 message. The option help messages are constructed by Getopts, so all
@@ -1630,27 +1647,27 @@ fn main() {
 
     let mut opts = Options::new();
     opts.optflag("h", "help", "Show this usage message.");
-    
+
     let matches = match opts.parse(&args[1..]) {
         Ok(m)  => { m }
                Err(e) => { panic!(e.to_string()) }
     };
-       
+
     if matches.opt_present("h") {
         print_usage(&program, opts);
                return;
        }
-               
+
        let data_file = args[1].clone();
        let data_path = Path::new(&data_file);
        let city = args[2].clone();
-       
+
        let file = fs::File::open(data_path).unwrap();
        let mut rdr = csv::Reader::from_reader(file);
-       
+
        for row in rdr.decode::<Row>() {
                let row = row.unwrap();
-       
+
                if row.city == city {
                        println!("{}, {}: {:?}",
                                row.city, row.country,
@@ -1756,7 +1773,7 @@ fn main() {
                print_usage(&program, opts);
                return;
        }
-               
+
        let data_file = args[1].clone();
        let data_path = Path::new(&data_file);
        let city = args[2].clone();
@@ -1838,7 +1855,7 @@ In our program, we accept a single file for input and do one pass over the
 data. This means we probably should be able to accept input on stdin. But maybe
 we like the current format too—so let's have both!
 
-Adding support for stdin is actually quite easy. There are only two things we
+Adding support for stdin is actually quite easy. There are only three things we
 have to do:
 
 1. Tweak the program arguments so that a single parameter—the
@@ -1865,7 +1882,7 @@ opts.optflag("h", "help", "Show this usage message.");
 ...
 let file = matches.opt_str("f");
 let data_file = file.as_ref().map(Path::new);
-       
+
 let city = if !matches.free.is_empty() {
        matches.free[0].clone()
 } else {
@@ -1879,9 +1896,9 @@ for pop in search(&data_file, &city) {
 ...
 ```
 
-In this peice of code, we take `file` (which has the type
+In this piece of code, we take `file` (which has the type
 `Option<String>`), and convert it to a type that `search` can use, in
-this case, `&Option<AsRef<Path>>`. Do do this, we take a reference of
+this case, `&Option<AsRef<Path>>`. To do this, we take a reference of
 file, and map `Path::new` onto it. In this case, `as_ref()` converts
 the `Option<String>` into an `Option<&str>`, and from there, we can
 execute `Path::new` to the content of the optional, and return the
@@ -2040,14 +2057,14 @@ so. This can be a little clumsy, especially if you intend for the program to
 be used in shell scripts.
 
 So let's start by adding the flags. Like before, we need to tweak the usage
-string and add a flag to the Option variable. Once were done that, Getopts does the rest:
+string and add a flag to the Option variable. Once we've done that, Getopts does the rest:
 
 ```rust,ignore
 ...
 let mut opts = Options::new();
 opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME");
 opts.optflag("h", "help", "Show this usage message.");
-opts.optflag("q", "quit", "Silences errors and warnings.");
+opts.optflag("q", "quiet", "Silences errors and warnings.");
 ...
 ```
 
@@ -2103,7 +2120,7 @@ heuristics!
   and
   [`Error`](../std/error/trait.Error.html)
   impls to make the [`try!`](../std/macro.try!.html)
-  macro more ergnomic.
+  macro more ergonomic.
 * If you're writing a library and your code can produce errors, define your own
   error type and implement the
   [`std::error::Error`](../std/error/trait.Error.html)
index d0825e543f2c288c678515ad8115d17b28ed1b0d..549f8c3ca5724e23a962b48a821d482e9b09f59c 100644 (file)
@@ -1,5 +1,5 @@
 % Getting Started
 
-This first section of the book will get you going with Rust and its tooling.
+This first section of the book will get us going with Rust and its tooling.
 First, we’ll install Rust. Then, the classic ‘Hello World’ program. Finally,
 we’ll talk about Cargo, Rust’s build system and package manager.
index 6a5a45fdb2c4412893455999eacbd64aa119b5a8..0956580ade0bb0ea3f88fc27a64e22c2a4342549 100644 (file)
@@ -38,11 +38,19 @@ let z = (8, 2, 6);
 
 In the example above `x` and `y` have arity 2. `z` has arity 3.
 
+### Bounds
+
+Bounds are constraints on a type or [trait][traits]. For example, if a bound
+is placed on the argument a function takes, types passed to that function
+must abide by that constraint.
+
+[traits]: traits.html
+
 ### DST (Dynamically Sized Type)
 
 A type without a statically known size or alignment. ([more info][link])
 
-[link]: ../nomicon/exotic-sizes.html#dynamically-sized-types-(dsts)
+[link]: ../nomicon/exotic-sizes.html#dynamically-sized-types-dsts
 
 ### Expression
 
index 4a35022b03c916bd5a23c5a82b4b165bd7f099a7..db484a28cb02c4a0e57388d8c1a4d51c8954da36 100644 (file)
@@ -99,9 +99,12 @@ use std::io;
 We’ll need to take user input, and then print the result as output. As such, we
 need the `io` library from the standard library. Rust only imports a few things
 by default into every program, [the ‘prelude’][prelude]. If it’s not in the
-prelude, you’ll have to `use` it directly.
+prelude, you’ll have to `use` it directly. There is also a second ‘prelude’, the
+[`io` prelude][ioprelude], which serves a similar function: you import it, and it
+imports a number of useful, `io`-related things.
 
 [prelude]: ../std/prelude/index.html
+[ioprelude]: ../std/io/prelude/index.html
 
 ```rust,ignore
 fn main() {
@@ -147,7 +150,7 @@ a few tricks up their sleeves.
 
 For example, they’re [immutable][immutable] by default. That’s why our example
 uses `mut`: it makes a binding mutable, rather than immutable. `let` doesn’t
-take a name on the left hand side, it actually accepts a
+take a name on the left hand side of the assignment, it actually accepts a
 ‘[pattern][patterns]’. We’ll use patterns later. It’s easy enough
 to use for now:
 
@@ -599,7 +602,7 @@ With this definition, anything of type `Foo` can be either a
 `Foo::Bar` or a `Foo::Baz`. We use the `::` to indicate the
 namespace for a particular `enum` variant.
 
-The [`Ordering`][ordering] enum has three possible variants: `Less`, `Equal`,
+The [`Ordering`][ordering] `enum` has three possible variants: `Less`, `Equal`,
 and `Greater`. The `match` statement takes a value of a type, and lets you
 create an ‘arm’ for each possible value. Since we have three types of
 `Ordering`, we have three arms:
@@ -918,9 +921,9 @@ let guess: u32 = match guess.trim().parse() {
 
 This is how you generally move from ‘crash on error’ to ‘actually handle the
 error’, by switching from `ok().expect()` to a `match` statement. The `Result`
-returned by `parse()` is an enum just like `Ordering`, but in this case, each
+returned by `parse()` is an `enum` just like `Ordering`, but in this case, each
 variant has some data associated with it: `Ok` is a success, and `Err` is a
-failure. Each contains more information: the successful parsed integer, or an
+failure. Each contains more information: the successfully parsed integer, or an
 error type. In this case, we `match` on `Ok(num)`, which sets the inner value
 of the `Ok` to the name `num`, and then we just return it on the right-hand
 side. In the `Err` case, we don’t care what kind of error it is, so we just
index 4bd7de23f0cd6648b4786fa3798a9b7de0bb7b1b..b155a4287e879a403228333864cface493b449d1 100644 (file)
@@ -7,15 +7,16 @@ so it is assumed that Rust projects will use Cargo from the beginning.
 
 [cratesio]: http://doc.crates.io
 
-Cargo manages three things: building your code, downloading the dependencies
-your code needs, and building those dependencies. At first, your program doesn’t
-have any dependencies, so we’ll only be using the first part of its
-functionality. Eventually, we’ll add more. Since we started off by using Cargo,
-it'll be easy to add later.
+Cargo manages three things: building our code, downloading the dependencies our
+code needs, and building those dependencies. At first, our program doesn’t have
+any dependencies, so we’ll only be using the first part of its functionality.
+Eventually, we’ll add more. Since we started off by using Cargo, it'll be easy
+to add later.
 
-If we installed Rust via the official installers we will also have Cargo. If we
-installed Rust some other way, we may want to [check the Cargo
-README][cargoreadme] for specific instructions about installing it.
+If you installed Rust via the official installers you will also have Cargo. If
+you installed Rust some other way, you may want to
+[check the Cargo README][cargoreadme] for specific instructions about installing
+it.
 
 [cargoreadme]: https://github.com/rust-lang/cargo#installing-cargo-from-nightlies
 
@@ -30,29 +31,29 @@ old executable (`main.exe` on Windows, `main` everywhere else). Let's do that pa
 ```bash
 $ mkdir src
 $ mv main.rs src/main.rs
-$ rm main  # or main.exe on Windows
+$ rm main  # or 'rm main.exe' on Windows
 ```
 
-Note that since we're creating an executable, we retain `main.rs` as the source
-filename. If we want to make a library instead, we should use `lib.rs`. This
-convention is used by Cargo to successfully compile our projects, but it can be
-overridden if we wish. Custom file locations for the entry point can be
-specified with a [`[lib]` or `[[bin]]`][crates-custom] key in the TOML file.
+> Note: since we're creating an executable, we retain `main.rs` as the source
+filename. If we want to make a library instead, we should use `lib.rs`. This
+> convention is used by Cargo to successfully compile our projects, but it can
+> be overridden if we wish. Custom file locations for the entry point can be
+specified with a [`[lib]` or `[[bin]]`][crates-custom] key in the TOML file.
 
 [crates-custom]: http://doc.crates.io/manifest.html#configuring-a-target
 
-Cargo expects your source files to live inside a `src` directory. That leaves
-the top level for other things, like READMEs, license information, and anything
-not related to your code. Cargo helps us keep our projects nice and tidy. A
-place for everything, and everything in its place.
+Cargo expects our source files to live inside a `src` directory. That leaves the
+top level for other things, like READMEs, license information, and anything not
+related to our code. Cargo helps us keep our projects nice and tidy. A place for
+everything, and everything in its place.
 
 Next, our configuration file:
 
 ```bash
-$ editor Cargo.toml
+$ editor Cargo.toml # or 'notepad Cargo.toml' on Windows
 ```
 
-Make sure to get this name right: you need the capital `C`!
+Make sure to get this name right: we need the capital `C`!
 
 Put this inside:
 
@@ -109,8 +110,8 @@ about the future: when our project gets more complex, we need to do more
 things to get all of the parts to properly compile. With Cargo, as our project
 grows, we can just run `cargo build`, and it’ll work the right way.
 
-When your project is finally ready for release, you can use
-`cargo build --release` to compile your project with optimizations.
+When our project is finally ready for release, we can use `cargo build
+--release` to compile our project with optimizations.
 
 You'll also notice that Cargo has created a new file: `Cargo.lock`.
 
@@ -120,14 +121,14 @@ name = "hello_world"
 version = "0.0.1"
 ```
 
-The `Cargo.lock` file is used by Cargo to keep track of dependencies in your application.
-Right now, we don’t have any, so it’s a bit sparse. You won't ever need
-to touch this file yourself, just let Cargo handle it.
+The `Cargo.lock` file is used by Cargo to keep track of dependencies in our
+application. Right now, we don’t have any, so it’s a bit sparse. We won't ever
+need to touch this file ourselves, just let Cargo handle it.
 
 That’s it! We’ve successfully built `hello_world` with Cargo. Even though our
-program is simple, it’s using much of the real tooling that you’ll use for the
-rest of your Rust career. You can expect to do this to get started with
-virtually all Rust projects:
+program is simple, it’s using much of the real tooling that we’ll use for the
+rest of our Rust career. We can expect to do this to get started with virtually
+all Rust projects:
 
 ```bash
 $ git clone someurl.com/foo
@@ -137,17 +138,19 @@ $ cargo build
 
 ## A New Project
 
-You don’t have to go through this whole process every time you want to start a
-new project! Cargo has the ability to make a bare-bones project directory in
-which you can start developing right away.
+We don’t have to go through this whole process every time we want to start a new
+project! Cargo has the ability to make a bare-bones project directory in which
+we can start developing right away.
 
-To start a new project with Cargo, use `cargo new`:
+To start a new project with Cargo, we use `cargo new`:
 
 ```bash
 $ cargo new hello_world --bin
 ```
 
-We’re passing `--bin` because our goal is to get straight to making an executable application, as opposed to a library. Executables are often called ‘binaries.’ (as in `/usr/bin`, if you’re on a Unix system)
+We’re passing `--bin` because our goal is to get straight to making an
+executable application, as opposed to a library. Executables are often called
+‘binaries.’ (as in `/usr/bin`, if we’re on a Unix system)
 
 Let's check out what Cargo has generated for us:
 
@@ -162,7 +165,7 @@ $ tree .
 1 directory, 2 files
 ```
 
-If you don't have the `tree` command, you can probably get it from your
+If we don't have the `tree` command, we can probably get it from our
 distribution’s package manager. It’s not necessary, but it’s certainly useful.
 
 This is all we need to get started. First, let’s check out `Cargo.toml`:
@@ -176,7 +179,7 @@ authors = ["Your Name <you@example.com>"]
 ```
 
 Cargo has populated this file with reasonable defaults based off the arguments
-you gave it and your `git` global configuration. You may notice that Cargo has
+we gave it and our `git` global configuration. You may notice that Cargo has
 also initialized the `hello_world` directory as a `git` repository.
 
 Here’s what’s in `src/main.rs`:
@@ -187,20 +190,21 @@ fn main() {
 }
 ```
 
-Cargo has generated a "Hello World!" for us, and you’re ready to start coding! Cargo
-has its own [guide][guide] which covers Cargo’s features in much more depth.
+Cargo has generated a "Hello World!" for us, and we’re ready to start coding!
+Cargo has its own [guide][guide] which covers Cargo’s features in much more
+depth.
 
 [guide]: http://doc.crates.io/guide.html
 
-Now that you’ve got the tools down, let’s actually learn more about the Rust
-language itself. These are the basics that will serve you well through the rest
-of your time with Rust.
+Now that we’ve got the tools down, let’s actually learn more about the Rust
+language itself. These are the basics that will serve us well through the rest
+of our time with Rust.
 
 You have two options: Dive into a project with ‘[Learn Rust][learnrust]’, or
-start from the bottom and work your way up with ‘[Syntax and
-Semantics][syntax]’. More experienced systems programmers will probably prefer
-‘Learn Rust’, while those from dynamic backgrounds may enjoy either. Different
-people learn differently! Choose whatever’s right for you.
+start from the bottom and work your way up with
+‘[Syntax and Semantics][syntax]’. More experienced systems programmers will
+probably prefer ‘Learn Rust’, while those from dynamic backgrounds may enjoy
+either. Different people learn differently! Choose whatever’s right for you.
 
 [learnrust]: learn-rust.html
 [syntax]: syntax-and-semantics.html
index cd4326a28d80967f41b85cc6b058b8a62e71ee93..2f9166751d96564e9cb7583547291b6a606da870 100644 (file)
@@ -1,25 +1,25 @@
 % Hello, world!
 
-Now that you have Rust installed, let’s write your first Rust program. It’s
-traditional to make your first program in any new language one that prints the
+Now that we have Rust installed, let’s write our first Rust program. It’s
+traditional to make our first program in any new language one that prints the
 text “Hello, world!” to the screen. The nice thing about starting with such a
-simple program is that you can verify that your compiler isn’t just installed,
-but also working properly. And printing information to the screen is a pretty
-common thing to do.
+simple program is that we can verify that our compiler isn’t just installed, but
+also working properly. And printing information to the screen is a pretty common
+thing to do.
 
-The first thing that we need to do is make a file to put our code in. I like
-to make a `projects` directory in my home directory, and keep all my projects
-there. Rust does not care where your code lives.
+The first thing that we need to do is make a file to put our code in. I like to
+make a `projects` directory in my home directory, and keep all my projects
+there. Rust doesn't care where our code lives.
 
 This actually leads to one other concern we should address: this guide will
-assume that you have basic familiarity with the command line. Rust itself makes
-no specific demands on your editing tooling, or where your code lives. If you
-prefer an IDE to the command line, you may want to check out
-[SolidOak][solidoak], or wherever plugins are for your favorite IDE. There are
-number of extensions of varying quality in development by the community. The
-Rust team also ships [plugins for various editors][plugins]. Configuring your
+assume that we have basic familiarity with the command line. Rust itself makes
+no specific demands on our editing tooling, or where our code lives. If we
+prefer an IDE to the command line, we may want to check out
+[SolidOak][solidoak], or wherever plugins are for our favorite IDE. There are a
+number of extensions of varying quality in development by the community. The
+Rust team also ships [plugins for various editors][plugins]. Configuring our
 editor or IDE is out of the scope of this tutorial, so check the documentation
-for your setup, specifically.
+for our setup, specifically.
 
 [solidoak]: https://github.com/oakes/SolidOak
 [plugins]: https://github.com/rust-lang/rust/blob/master/src/etc/CONFIGS.md
@@ -33,14 +33,15 @@ $ mkdir hello_world
 $ cd hello_world
 ```
 
-If you’re on Windows and not using PowerShell, the `~` may not work. Consult
-the documentation for your shell for more details.
+If we’re on Windows and not using PowerShell, the `~` may not work. Consult the
+documentation for our shell for more details.
 
 Let’s make a new source file next. We’ll call our file `main.rs`. Rust files
-always end in a `.rs` extension. If you’re using more than one word in your
-filename, use an underscore: `hello_world.rs` rather than `helloworld.rs`.
+always end in a `.rs` extension, and if we’re using more than one word in a
+Rust filename, we use an underscore: for example, `linked_list.rs`, not
+`linkedlist.rs` or `LinkedList.rs`.
 
-Now that you’ve got your file open, type this in:
+Now that we’ve got our file open, type this in:
 
 ```rust
 fn main() {
@@ -48,7 +49,7 @@ fn main() {
 }
 ```
 
-Save the file, and then type this into your terminal window:
+Save the file, and then type this into our terminal window:
 
 ```bash
 $ rustc main.rs
@@ -72,9 +73,9 @@ we aren’t returning anything from this function, we can omit the return type
 entirely. We’ll get to it later.
 
 You’ll also note that the function is wrapped in curly braces (`{` and `}`).
-Rust requires these around all function bodies. It is also considered good
-style to put the opening curly brace on the same line as the function
-declaration, with one space in between.
+Rust requires these around all function bodies. It is also considered good style
+to put the opening curly brace on the same line as the function declaration,
+with one space in between.
 
 Next up is this line:
 
@@ -85,29 +86,30 @@ Next up is this line:
 This line does all of the work in our little program. There are a number of
 details that are important here. The first is that it’s indented with four
 spaces, not tabs. Please configure your editor of choice to insert four spaces
-with the tab key. We provide some [sample configurations for various
-editors][configs].
+with the tab key. We provide some
+[sample configurations for various editors][configs].
 
 [configs]: https://github.com/rust-lang/rust/tree/master/src/etc/CONFIGS.md
 
-The second point is the `println!()` part. This is calling a Rust [macro][macro],
-which is how metaprogramming is done in Rust. If it were a function instead, it
-would look like this: `println()`. For our purposes, we don’t need to worry
-about this difference. Just know that sometimes, you’ll see a `!`, and that
-means that you’re calling a macro instead of a normal function. Rust implements
-`println!` as a macro rather than a function for good reasons, but that's an
-advanced topic. One last thing to mention: Rust’s macros are significantly
-different from C macros, if you’ve used those. Don’t be scared of using macros.
-We’ll get to the details eventually, you’ll just have to trust us for now.
+The second point is the `println!()` part. This is calling a Rust
+[macro][macro], which is how metaprogramming is done in Rust. If it were a
+function instead, it would look like this: `println()`. For our purposes, we
+don’t need to worry about this difference. Just know that sometimes, we’ll see a
+`!`, and that means that we’re calling a macro instead of a normal function.
+Rust implements `println!` as a macro rather than a function for good reasons,
+but that's an advanced topic. One last thing to mention: Rust’s macros are
+significantly different from C macros, if you’ve used those. Don’t be scared of
+using macros. We’ll get to the details eventually, you’ll just have to take it
+on trust for now.
 
 [macro]: macros.html
 
 Next, `"Hello, world!"` is a ‘string’. Strings are a surprisingly complicated
 topic in a systems programming language, and this is a ‘statically allocated’
-string. If you want to read further about allocation, check out
-[the stack and the heap][allocation], but you don’t need to right now if you
-don’t want to. We pass this string as an argument to `println!`, which prints the
-string to the screen. Easy enough!
+string. If you want to read further about allocation, check out [the stack and
+the heap][allocation], but you don’t need to right now if you don’t want to. We
+pass this string as an argument to `println!`, which prints the string to the
+screen. Easy enough!
 
 [allocation]: the-stack-and-the-heap.html
 
@@ -126,8 +128,8 @@ compiler, `rustc`, by passing it the name of our source file:
 $ rustc main.rs
 ```
 
-This is similar to `gcc` or `clang`, if you come from a C or C++ background. Rust
-will output a binary executable. You can see it with `ls`:
+This is similar to `gcc` or `clang`, if you come from a C or C++ background.
+Rust will output a binary executable. We can see it with `ls`:
 
 ```bash
 $ ls
@@ -142,7 +144,7 @@ main.exe  main.rs
 ```
 
 There are now two files: our source code, with the `.rs` extension, and the
-executable (`main.exe` on Windows, `main` everywhere else)
+executable (`main.exe` on Windows, `main` everywhere else).
 
 ```bash
 $ ./main  # or main.exe on Windows
@@ -150,20 +152,20 @@ $ ./main  # or main.exe on Windows
 
 This prints out our `Hello, world!` text to our terminal.
 
-If you come from a dynamic language like Ruby, Python, or JavaScript,
-you may not be used to these two steps being separate. Rust is an
-‘ahead-of-time compiled language’, which means that you can compile a program,
-give it to someone else, and they don't need to have Rust installed. If you
-give someone a `.rb` or `.py` or `.js` file, they need to have a
-Ruby/Python/JavaScript implementation installed, but you just need one command
-to both compile and run your program. Everything is a tradeoff in language
-design, and Rust has made its choice.
+If you come from a dynamic language like Ruby, Python, or JavaScript, you may
+not be used to these two steps being separate. Rust is an ‘ahead-of-time
+compiled language’, which means that we can compile a program, give it to
+someone else, and they don't need to have Rust installed. If we give someone a
+`.rb` or `.py` or `.js` file, they need to have a Ruby/Python/JavaScript
+implementation installed, but we just need one command to both compile and run
+our program. Everything is a tradeoff in language design, and Rust has made its
+choice.
 
 Congratulations! You have officially written a Rust program. That makes you a
 Rust programmer! Welcome. 🎊🎉👍
 
 Next, I'd like to introduce you to another tool, Cargo, which is used to write
 real-world Rust programs. Just using `rustc` is nice for simple things, but as
-your project grows, you'll want something to help you manage all of the options
-that it has, and to make it easy to share your code with other people and
+our project grows, we'll want something to help us manage all of the options
+that it has, and to make it easy to share our code with other people and
 projects.
index 4872ed6a773472a8412e115fd4c1302dd2f7e5e8..faa922acb3de282805cb17f898d2c08f92f6d72d 100644 (file)
@@ -41,7 +41,7 @@ If a [pattern][patterns] matches successfully, it binds any appropriate parts of
 the value to the identifiers in the pattern, then evaluates the expression. If
 the pattern doesn’t match, nothing happens.
 
-If you’d rather to do something else when the pattern does not match, you can
+If you want to do something else when the pattern does not match, you can
 use `else`:
 
 ```rust
@@ -65,7 +65,7 @@ loop as long as a value matches a certain pattern. It turns code like this:
 loop {
     match option {
         Some(x) => println!("{}", x),
-        _ => break,
+        None => break,
     }
 }
 ```
index f06005d55b9616d6b96b5072ec187c552566c0dd..49ee5317c78838e2fb79043dd76c8c57eadaf598 100644 (file)
@@ -1,21 +1,21 @@
 % Installing Rust
 
 The first step to using Rust is to install it! There are a number of ways to
-install Rust, but the easiest is to use the `rustup` script. If you're on Linux
-or a Mac, all you need to do is this:
+install Rust, but the easiest is to use the `rustup` script. If we're on Linux
+or a Mac, all we need to do is this:
 
-> Note: you don't need to type in the `$`s, they just indicate the start of
-> each command. You’ll see many tutorials and examples around the web that
-> follow this convention: `$` for commands run as your regular user, and
-> `#` for commands you should be running as an administrator.
+> Note: we don't need to type in the `$`s, they are there to indicate the start of
+> each command. We’ll see many tutorials and examples around the web that
+> follow this convention: `$` for commands run as our regular user, and `#` for
+> commands we should be running as an administrator.
 
 ```bash
 $ curl -sf -L https://static.rust-lang.org/rustup.sh | sh
 ```
 
-If you're concerned about the [potential insecurity][insecurity] of using `curl
-| sh`, please keep reading and see our disclaimer below. And feel free to
-use a two-step version of the installation and examine our installation script:
+If we're concerned about the [potential insecurity][insecurity] of using `curl |
+sh`, please keep reading and see our disclaimer below. And feel free to use a
+two-step version of the installation and examine our installation script:
 
 ```bash
 $ curl -f -L https://static.rust-lang.org/rustup.sh -O
@@ -25,11 +25,12 @@ $ sh rustup.sh
 [insecurity]: http://curlpipesh.tumblr.com
 
 If you're on Windows, please download the appropriate [installer][install-page].
-**NOTE:** By default, the Windows installer will not add Rust to the %PATH%
-system variable. If this is the only version of Rust you are installing and you
-want to be able to run it from the command line, click on "Advanced" on the
-install dialog and on the "Product Features" page ensure "Add to PATH" is
-installed on the local hard drive.
+
+> Note: By default, the Windows installer won't add Rust to the %PATH% system
+> variable. If this is the only version of Rust we are installing and we want to
+> be able to run it from the command line, click on "Advanced" on the install
+> dialog and on the "Product Features" page ensure "Add to PATH" is installed on
+> the local hard drive.
 
 
 [install-page]: https://www.rust-lang.org/install.html
@@ -37,78 +38,145 @@ installed on the local hard drive.
 ## Uninstalling
 
 If you decide you don't want Rust anymore, we'll be a bit sad, but that's okay.
-Not every programming language is great for everyone. Just run the uninstall
-script:
+Not every programming language is great for everyone. We can run the
+uninstall script:
 
 ```bash
 $ sudo /usr/local/lib/rustlib/uninstall.sh
 ```
 
-If you used the Windows installer, just re-run the `.msi` and it will give you
-an uninstall option.
+If we used the Windows installer, we can re-run the `.msi` and it will give
+us an uninstall option.
 
 ## That disclaimer we promised
 
-Some people, and somewhat rightfully so, get very upset when we tell you to
-`curl | sh`. Basically, when you do this, you are trusting that the good
-people who maintain Rust aren't going to hack your computer and do bad things.
-That's a good instinct! If you're one of those people, please check out the
-documentation on [building Rust from Source][from-source], or [the official
-binary downloads][install-page].
+Some people, and somewhat rightfully so, get very upset when we tell them to
+`curl | sh`. Their concern is that `curl | sh` implicitly requires you to trust
+that the good people who maintain Rust aren't going to hack your computer and
+do bad things — and even having accepted that, there is still the possibility
+that the Rust website has been hacked and the `rustup` script compromised.
+
+Being wary of such possibilities is a good instinct! If you're uncomfortable
+using `curl | sh` for reasons like these, please check out the documentation on
+[building Rust from Source][from-source], or
+[the official binary downloads][install-page].
 
 [from-source]: https://github.com/rust-lang/rust#building-from-source
 
 ## Platform support
 
-Oh, we should also mention the officially supported platforms:
-
-* Windows (7, 8, Server 2008 R2)
-* Linux (2.6.18 or later, various distributions), x86 and x86-64
-* OSX 10.7 (Lion) or greater, x86 and x86-64
-
-We extensively test Rust on these platforms, and a few others, too, like
-Android. But these are the ones most likely to work, as they have the most
-testing.
-
-Finally, a comment about Windows. Rust considers Windows to be a first-class
-platform upon release, but if we're honest, the Windows experience isn't as
-integrated as the Linux/OS X experience is. We're working on it! If anything
-does not work, it is a bug. Please let us know if that happens. Each and every
-commit is tested against Windows just like any other platform.
+The Rust compiler runs on, and compiles to, a great number of platforms, though
+not all platforms are equally supported. Rust's support levels are organized
+into three tiers, each with a different set of guarantees.
+
+Platforms are identified by their "target triple" which is the string to inform
+the compiler what kind of output should be produced. The columns below indicate
+whether the corresponding component works on the specified platform.
+
+### Tier 1
+
+Tier 1 platforms can be thought of as "guaranteed to build and work".
+Specifically they will each satisfy the following requirements:
+
+* Automated testing is set up to run tests for the platform.
+* Landing changes to the `rust-lang/rust` repository's master branch is gated on
+  tests passing.
+* Official release artifacts are provided for the platform.
+* Documentation for how to use and how to build the platform is available.
+
+|  Target                       | std |rustc|cargo| notes                      |
+|-------------------------------|-----|-----|-----|----------------------------|
+| `x86_64-pc-windows-msvc`      |  ✓  |  ✓  |  ✓  | 64-bit MSVC (Windows 7+)   |
+| `i686-pc-windows-gnu`         |  ✓  |  ✓  |  ✓  | 32-bit MinGW (Windows 7+)  |
+| `x86_64-pc-windows-gnu`       |  ✓  |  ✓  |  ✓  | 64-bit MinGW (Windows 7+)  |
+| `i686-apple-darwin`           |  ✓  |  ✓  |  ✓  | 32-bit OSX (10.7+, Lion+)  |
+| `x86_64-apple-darwin`         |  ✓  |  ✓  |  ✓  | 64-bit OSX (10.7+, Lion+)  |
+| `i686-unknown-linux-gnu`      |  ✓  |  ✓  |  ✓  | 32-bit Linux (2.6.18+)     |
+| `x86_64-unknown-linux-gnu`    |  ✓  |  ✓  |  ✓  | 64-bit Linux (2.6.18+)     |
+
+### Tier 2
+
+Tier 2 platforms can be thought of as "guaranteed to build". Automated tests are
+not run so it's not guaranteed to produce a working build, but platforms often
+work to quite a good degree and patches are always welcome! Specifically, these
+platforms are required to have each of the following:
+
+* Automated building is set up, but may not be running tests.
+* Landing changes to the `rust-lang/rust` repository's master branch is gated on
+  platforms **building**. Note that this means for some platforms only the
+  standard library is compiled, but for others the full bootstrap is run.
+* Official release artifacts are provided for the platform.
+
+|  Target                       | std |rustc|cargo| notes                      |
+|-------------------------------|-----|-----|-----|----------------------------|
+| `i686-pc-windows-msvc`        |  ✓  |  ✓  |  ✓  | 32-bit MSVC (Windows 7+)   |
+
+### Tier 3
+
+Tier 3 platforms are those which Rust has support for, but landing changes is
+not gated on the platform either building or passing tests. Working builds for
+these platforms may be spotty as their reliability is often defined in terms of
+community contributions. Additionally, release artifacts and installers are not
+provided, but there may be community infrastructure producing these in
+unofficial locations.
+
+|  Target                       | std |rustc|cargo| notes                      |
+|-------------------------------|-----|-----|-----|----------------------------|
+| `x86_64-unknown-linux-musl`   |  ✓  |     |     | 64-bit Linux with MUSL     |
+| `arm-linux-androideabi`       |  ✓  |     |     | ARM Android                |
+| `i686-linux-android`          |  ✓  |     |     | 32-bit x86 Android         |
+| `aarch64-linux-android`       |  ✓  |     |     | ARM64 Android              |
+| `arm-unknown-linux-gnueabi`   |  ✓  |  ✓  |     | ARM Linux (2.6.18+)        |
+| `arm-unknown-linux-gnueabihf` |  ✓  |  ✓  |     | ARM Linux (2.6.18+)        |
+| `aarch64-unknown-linux-gnu`   |  ✓  |     |     | ARM64 Linux (2.6.18+)      |
+| `mips-unknown-linux-gnu`      |  ✓  |     |     | MIPS Linux (2.6.18+)       |
+| `mipsel-unknown-linux-gnu`    |  ✓  |     |     | MIPS (LE) Linux (2.6.18+)  |
+| `powerpc-unknown-linux-gnu`   |  ✓  |     |     | PowerPC Linux (2.6.18+)    |
+| `i386-apple-ios`              |  ✓  |     |     | 32-bit x86 iOS             |
+| `x86_64-apple-ios`            |  ✓  |     |     | 64-bit x86 iOS             |
+| `armv7-apple-ios`             |  ✓  |     |     | ARM iOS                    |
+| `armv7s-apple-ios`            |  ✓  |     |     | ARM iOS                    |
+| `aarch64-apple-ios`           |  ✓  |     |     | ARM64 iOS                  |
+| `i686-unknown-freebsd`        |  ✓  |  ✓  |     | 32-bit FreeBSD             |
+| `x86_64-unknown-freebsd`      |  ✓  |  ✓  |     | 64-bit FreeBSD             |
+| `x86_64-unknown-openbsd`      |  ✓  |  ✓  |     | 64-bit OpenBSD             |
+| `x86_64-unknown-netbsd`       |  ✓  |  ✓  |     | 64-bit NetBSD              |
+| `x86_64-unknown-bitrig`       |  ✓  |  ✓  |     | 64-bit Bitrig              |
+| `x86_64-unknown-dragonfly`    |  ✓  |  ✓  |     | 64-bit DragonFlyBSD        |
+| `x86_64-rumprun-netbsd`       |  ✓  |     |     | 64-bit NetBSD Rump Kernel  |
+| `i686-pc-windows-msvc` (XP)   |  ✓  |     |     | Windows XP support         |
+| `x86_64-pc-windows-msvc` (XP) |  ✓  |     |     | Windows XP support         |
+
+Note that this table can be expanded over time, this isn't the exhaustive set of
+tier 3 platforms that will ever be!
 
 ## After installation
 
-If you've got Rust installed, you can open up a shell, and type this:
+If we've got Rust installed, we can open up a shell, and type this:
 
 ```bash
 $ rustc --version
 ```
 
-You should see the version number, commit hash, and commit date. If you just
-installed version 1.2.0, you should see:
+You should see the version number, commit hash, and commit date.
 
-```bash
-rustc 1.2.0 (082e47636 2015-08-03)
-```
+If you do, Rust has been installed successfully! Congrats!
 
-If you did, Rust has been installed successfully! Congrats!
-
-If you didn't and you're on Windows, check that Rust is in your %PATH% system
+If you don't and you're on Windows, check that Rust is in your %PATH% system
 variable. If it isn't, run the installer again, select "Change" on the "Change,
 repair, or remove installation" page and ensure "Add to PATH" is installed on
 the local hard drive.
 
-This installer also installs a copy of the documentation locally, so you can
-read it offline. On UNIX systems, `/usr/local/share/doc/rust` is the location.
-On Windows, it's in a `share/doc` directory, inside wherever you installed Rust
-to.
-
-If not, there are a number of places where you can get help. The easiest is
-[the #rust IRC channel on irc.mozilla.org][irc], which you can access through
-[Mibbit][mibbit]. Click that link, and you'll be chatting with other Rustaceans
-(a silly nickname we call ourselves), and we can help you out. Other great
-resources include [the user’s forum][users], and
-[Stack Overflow][stackoverflow].
+This installer also installs a copy of the documentation locally, so we can read
+it offline. On UNIX systems, `/usr/local/share/doc/rust` is the location. On
+Windows, it's in a `share/doc` directory, inside the directory to which Rust was
+installed.
+
+If not, there are a number of places where we can get help. The easiest is
+[the #rust IRC channel on irc.mozilla.org][irc], which we can access through
+[Mibbit][mibbit]. Click that link, and we'll be chatting with other Rustaceans
+(a silly nickname we call ourselves) who can help us out. Other great resources
+include [the user’s forum][users], and [Stack Overflow][stackoverflow].
 
 [irc]: irc://irc.mozilla.org/#rust
 [mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
index 1c574f02091f8574f956557d3b67c7a2a4d30413..c444f9f2fe53d420e5cbae1bbb63007e2c51d965 100644 (file)
@@ -42,12 +42,12 @@ loop is just a handy way to write this `loop`/`match`/`break` construct.
 `for` loops aren't the only thing that uses iterators, however. Writing your
 own iterator involves implementing the `Iterator` trait. While doing that is
 outside of the scope of this guide, Rust provides a number of useful iterators
-to accomplish various tasks. Before we talk about those, we should talk about a
-Rust anti-pattern. And that's using ranges like this.
+to accomplish various tasks. But first, a few notes about limitations of ranges.
 
-Yes, we just talked about how ranges are cool. But ranges are also very
-primitive. For example, if you needed to iterate over the contents of a vector,
-you may be tempted to write this:
+Ranges are very primitive, and we often can use better alternatives. Consider the
+following Rust anti-pattern: using ranges to emulate a C-style `for` loop. Let’s
+suppose you needed to iterate over the contents of a vector. You may be tempted
+to write this:
 
 ```rust
 let nums = vec![1, 2, 3];
@@ -101,10 +101,10 @@ So, now that we've established that ranges are often not what you want, let's
 talk about what you do want instead.
 
 There are three broad classes of things that are relevant here: iterators,
-*iterator adapters*, and *consumers*. Here's some definitions:
+*iterator adaptors*, and *consumers*. Here's some definitions:
 
 * *iterators* give you a sequence of values.
-* *iterator adapters* operate on an iterator, producing a new iterator with a
+* *iterator adaptors* operate on an iterator, producing a new iterator with a
   different output sequence.
 * *consumers* operate on an iterator, producing some final set of values.
 
@@ -150,15 +150,16 @@ let greater_than_forty_two = (0..100)
                              .find(|x| *x > 42);
 
 match greater_than_forty_two {
-    Some(_) => println!("We got some numbers!"),
-    None => println!("No numbers found :("),
+    Some(_) => println!("Found a match!"),
+    None => println!("No match found :("),
 }
 ```
 
 `find` takes a closure, and works on a reference to each element of an
 iterator. This closure returns `true` if the element is the element we're
-looking for, and `false` otherwise. Because we might not find a matching
-element, `find` returns an `Option` rather than the element itself.
+looking for, and `false` otherwise. `find` returns the first element satisfying
+the specified predicate. Because we might not find a matching element, `find`
+returns an `Option` rather than the element itself.
 
 Another important consumer is `fold`. Here's what it looks like:
 
@@ -245,12 +246,12 @@ for num in nums.iter() {
 These two basic iterators should serve you well. There are some more
 advanced iterators, including ones that are infinite.
 
-That's enough about iterators. Iterator adapters are the last concept
+That's enough about iterators. Iterator adaptors are the last concept
 we need to talk about with regards to iterators. Let's get to it!
 
-## Iterator adapters
+## Iterator adaptors
 
-*Iterator adapters* take an iterator and modify it somehow, producing
+*Iterator adaptors* take an iterator and modify it somehow, producing
 a new iterator. The simplest one is called `map`:
 
 ```rust,ignore
@@ -279,10 +280,9 @@ doesn't print any numbers:
 If you are trying to execute a closure on an iterator for its side effects,
 just use `for` instead.
 
-There are tons of interesting iterator adapters. `take(n)` will return an
-iterator over the next `n` elements of the original iterator. Note that this
-has no side effect on the original iterator. Let's try it out with our infinite
-iterator from before:
+There are tons of interesting iterator adaptors. `take(n)` will return an
+iterator over the next `n` elements of the original iterator. Let's try it out
+with an infinite iterator:
 
 ```rust
 for i in (1..).take(5) {
@@ -302,7 +302,7 @@ This will print
 
 `filter()` is an adapter that takes a closure as an argument. This closure
 returns `true` or `false`. The new iterator `filter()` produces
-only the elements that that closure returns `true` for:
+only the elements that the closure returns `true` for:
 
 ```rust
 for i in (1..100).filter(|&x| x % 2 == 0) {
@@ -329,7 +329,7 @@ a few times, and then consume the result. Check it out:
 
 This will give you a vector containing `6`, `12`, `18`, `24`, and `30`.
 
-This is just a small taste of what iterators, iterator adapters, and consumers
+This is just a small taste of what iterators, iterator adaptors, and consumers
 can help you with. There are a number of really useful iterators, and you can
 write your own as well. Iterators provide a safe, efficient way to manipulate
 all kinds of lists. They're a little unusual at first, but if you play with
index 62270cb45b5e6c17b0de97d410626c5aa77fece0..13265ab1eba12f1444e7382865021ddf027d9fdf 100644 (file)
@@ -1,6 +1,6 @@
 % Lifetimes
 
-This guide is one of three presenting Rust’s ownership system. This is one of
+This guide is three of three presenting Rust’s ownership system. This is one of
 Rust’s most unique and compelling features, with which Rust developers should
 become quite acquainted. Ownership is how Rust achieves its largest goal,
 memory safety. There are a few distinct concepts, each with its own chapter:
@@ -43,11 +43,11 @@ With that in mind, let’s learn about lifetimes.
 Lending out a reference to a resource that someone else owns can be
 complicated. For example, imagine this set of operations:
 
-- I acquire a handle to some kind of resource.
-- I lend you a reference to the resource.
-- I decide I’m done with the resource, and deallocate it, while you still have
+1. I acquire a handle to some kind of resource.
+2. I lend you a reference to the resource.
+3. I decide I’m done with the resource, and deallocate it, while you still have
   your reference.
-- You decide to use the resource.
+4. You decide to use the resource.
 
 Uh oh! Your reference is pointing to an invalid resource. This is called a
 dangling pointer or ‘use after free’, when the resource is memory.
@@ -70,9 +70,12 @@ fn bar<'a>(x: &'a i32) {
 ```
 
 The `'a` reads ‘the lifetime a’. Technically, every reference has some lifetime
-associated with it, but the compiler lets you elide them in common cases.
+associated with it, but the compiler lets you elide (i.e. omit, see
+["Lifetime Elision"][lifetime-elision] below) them in common cases.
 Before we get to that, though, let’s break the explicit example down:
 
+[lifetime-elision]: #lifetime-elision
+
 ```rust,ignore
 fn bar<'a>(...)
 ```
@@ -349,9 +352,9 @@ fn frob<'a, 'b>(s: &'a str, t: &'b str) -> &str; // Expanded: Output lifetime is
 fn get_mut(&mut self) -> &mut T; // elided
 fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
 
-fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command // elided
-fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded
+fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command; // elided
+fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expanded
 
 fn new(buf: &mut [u8]) -> BufWriter; // elided
-fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded
+fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>; // expanded
 ```
index a2bdd66b0c253e2954a11a4b17b7350961f9f6a1..d31d82324708243b887dd6d355f058f6e67f09a8 100644 (file)
@@ -55,7 +55,7 @@ kinds of things `foo` could be: `self` if it’s just a value on the stack,
 `&self` if it’s a reference, and `&mut self` if it’s a mutable reference.
 Because we took the `&self` parameter to `area`, we can use it just like any
 other parameter. Because we know it’s a `Circle`, we can access the `radius`
-just like we would with any other `struct`. 
+just like we would with any other `struct`.
 
 We should default to using `&self`, as you should prefer borrowing over taking
 ownership, as well as taking immutable references over mutable ones. Here’s an
index 2c4316e651a8e135b638ab7f2c0aca650fe89ce0..71acb551e6e3ccc05ca601099fd7b16933705c6b 100644 (file)
@@ -84,7 +84,7 @@ philosophy, memory safety, and the mechanism by which Rust guarantees it, the
 
 > You may have one or the other of these two kinds of borrows, but not both at
 > the same time:
-> 
+>
 > * one or more references (`&T`) to a resource,
 > * exactly one mutable reference (`&mut T`).
 
index 9abcd330989b4b85c12306356cdd79af5e442a0a..5fca05d5340068b543c5f24cc33cf5f30b42bf0a 100644 (file)
@@ -4,14 +4,6 @@ By default, `std` is linked to every Rust crate. In some contexts,
 this is undesirable, and can be avoided with the `#![no_std]`
 attribute attached to the crate.
 
-```ignore
-// a minimal library
-#![crate_type="lib"]
-#![feature(no_std)]
-#![no_std]
-# // fn main() {} tricked you, rustdoc!
-```
-
 Obviously there's more to life than just libraries: one can use
 `#[no_std]` with an executable, controlling the entry point is
 possible in two ways: the `#[start]` attribute, or overriding the
@@ -21,7 +13,10 @@ The function marked `#[start]` is passed the command line parameters
 in the same format as C:
 
 ```rust
-#![feature(lang_items, start, no_std, libc)]
+# #![feature(libc)]
+#![feature(lang_items)]
+#![feature(start)]
+#![feature(no_std)]
 #![no_std]
 
 // Pull in the system libc library for what crt0.o likely requires
@@ -47,11 +42,13 @@ with `#![no_main]` and then create the appropriate symbol with the
 correct ABI and the correct name, which requires overriding the
 compiler's name mangling too:
 
-```ignore
+```rust
+# #![feature(libc)]
 #![feature(no_std)]
+#![feature(lang_items)]
+#![feature(start)]
 #![no_std]
 #![no_main]
-#![feature(lang_items, start)]
 
 extern crate libc;
 
@@ -92,19 +89,24 @@ instead.
 
 The core library has very few dependencies and is much more portable than the
 standard library itself. Additionally, the core library has most of the
-necessary functionality for writing idiomatic and effective Rust code.
+necessary functionality for writing idiomatic and effective Rust code. When
+using `#![no_std]`, Rust will automatically inject the `core` crate, just like
+we do for `std` when we’re using it.
 
 As an example, here is a program that will calculate the dot product of two
 vectors provided from C, using idiomatic Rust practices.
 
-```ignore
-#![feature(lang_items, start, no_std, core, libc)]
+```rust
+# #![feature(libc)]
+#![feature(lang_items)]
+#![feature(start)]
+#![feature(no_std)]
+#![feature(core)]
+#![feature(core_slice_ext)]
+#![feature(raw)]
 #![no_std]
 
-# extern crate libc;
-extern crate core;
-
-use core::prelude::*;
+extern crate libc;
 
 use core::mem;
 
index 5ddbdd6df00b048c7dfc2284feeece0984bbbb1c..d8ef44b782a1de29ef0e8f0bfe043096b2f606ec 100644 (file)
@@ -42,7 +42,7 @@ With that in mind, let’s learn about ownership.
 # Ownership
 
 [Variable bindings][bindings] have a property in Rust: they ‘have ownership’
-of what they’re bound to. This means that when a binding goes out of scope, 
+of what they’re bound to. This means that when a binding goes out of scope,
 Rust will free the bound resources. For example:
 
 ```rust
@@ -158,8 +158,8 @@ has no pointers to data somewhere else, copying it is a full copy.
 
 All primitive types implement the `Copy` trait and their ownership is
 therefore not moved like one would assume, following the ´ownership rules´.
-To give an example, the two following snippets of code only compile because the 
-`i32` and `bool` types implement the `Copy` trait. 
+To give an example, the two following snippets of code only compile because the
+`i32` and `bool` types implement the `Copy` trait.
 
 ```rust
 fn main() {
@@ -236,13 +236,3 @@ complicated.
 Luckily, Rust offers a feature, borrowing, which helps us solve this problem.
 It’s the topic of the next section!
 
-
-
-
-
-
-
-
-
-
-
index a365732fe9bd14c115654cb84eb115769b025508..8f4a7a439553b8d4cf7f52ea7c4c42f50905fee0 100644 (file)
@@ -23,6 +23,31 @@ match x {
 
 This prints `one`.
 
+There’s one pitfall with patterns: like anything that introduces a new binding,
+they introduce shadowing. For example:
+
+```rust
+let x = 'x';
+let c = 'c';
+
+match c {
+    x => println!("x: {} c: {}", x, c),
+}
+
+println!("x: {}", x)
+```
+
+This prints:
+
+```text
+x: c c: c
+x: x
+```
+
+In other words, `x =>` matches the pattern and introduces a new binding named
+`x` that’s in scope for the match arm. Because we already have a binding named
+`x`, this new `x` shadows it.
+
 # Multiple patterns
 
 You can match multiple patterns with `|`:
@@ -299,7 +324,7 @@ match x {
 ```
 
 This prints `no`, because the `if` applies to the whole of `4 | 5`, and not to
-just the `5`, In other words, the the precedence of `if` behaves like this:
+just the `5`. In other words, the precedence of `if` behaves like this:
 
 ```text
 (4 | 5) if y => ...
index 027909dd058769c70031e0d32a8424a803c5e58b..a8c7a7d41573e4fa565a264cf829bc451f2e1b20 100644 (file)
@@ -162,13 +162,18 @@ A ‘slice’ is a reference to (or “view” into) another data structure. The
 useful for allowing safe, efficient access to a portion of an array without
 copying. For example, you might want to reference just one line of a file read
 into memory. By nature, a slice is not created directly, but from an existing
-variable. Slices have a length, can be mutable or not, and in many ways behave
-like arrays:
+variable binding. Slices have a defined length, can be mutable or immutable.
+
+## Slicing syntax
+
+You can use a combo of `&` and `[]` to create a slice from various things. The
+`&` indicates that slices are similar to references, and the `[]`s, with a
+range, let you define the length of the slice:
 
 ```rust
 let a = [0, 1, 2, 3, 4];
-let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
 let complete = &a[..]; // A slice containing all of the elements in a
+let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
 ```
 
 Slices have type `&[T]`. We’ll talk about that `T` when we cover
index 8a3b98b72927b3303f3146e076084347a327c014..679f5489ea8f4a331f1b25d7d5a0ba945d50052a 100644 (file)
@@ -98,16 +98,15 @@ these properties are true for any references, no matter how they are created,
 and so any conversion from raw pointers is asserting that they hold. The
 programmer *must* guarantee this.
 
-The recommended method for the conversion is
+The recommended method for the conversion is:
 
 ```rust
-let i: u32 = 1;
-
 // explicit cast
+let i: u32 = 1;
 let p_imm: *const u32 = &i as *const u32;
-let mut m: u32 = 2;
 
 // implicit coercion
+let mut m: u32 = 2;
 let p_mut: *mut u32 = &mut m;
 
 unsafe {
index 50297b266d98c1a6ff648127dab19b26d52f45ce..13cfecdf1a72904ff30f93835da140ce09fed19a 100644 (file)
@@ -1,6 +1,6 @@
 % References and Borrowing
 
-This guide is one of three presenting Rust’s ownership system. This is one of
+This guide is two of three presenting Rust’s ownership system. This is one of
 Rust’s most unique and compelling features, with which Rust developers should
 become quite acquainted. Ownership is how Rust achieves its largest goal,
 memory safety. There are a few distinct concepts, each with its own
@@ -233,7 +233,7 @@ So when we add the curly braces:
 ```rust
 let mut x = 5;
 
-{                   
+{
     let y = &mut x; // -+ &mut borrow starts here
     *y += 1;        //  |
 }                   // -+ ... and ends here
@@ -306,7 +306,7 @@ which was invalid. For example:
 
 ```rust,ignore
 let y: &i32;
-{ 
+{
     let x = 5;
     y = &x;
 }
@@ -323,7 +323,7 @@ error: `x` does not live long enough
 note: reference must be valid for the block suffix following statement 0 at
 2:16...
 let y: &i32;
-{ 
+{
     let x = 5;
     y = &x;
 }
@@ -363,7 +363,7 @@ note: reference must be valid for the block suffix following statement 0 at
     let y: &i32;
     let x = 5;
     y = &x;
-    
+
     println!("{}", y);
 }
 
@@ -371,7 +371,7 @@ note: ...but borrowed value is only valid for the block suffix following
 statement 1 at 3:14
     let x = 5;
     y = &x;
-    
+
     println!("{}", y);
 }
 ```
index 8dd2e365aa82ca46a29bf037f63989c9752f9730..5c0bde02f960591f98fb3fe7e7f3dacf827acd93 100644 (file)
@@ -108,7 +108,7 @@ fn process() {
     let handles: Vec<_> = (0..10).map(|_| {
         thread::spawn(|| {
             let mut x = 0;
-            for _ in (0..5_000_000) {
+            for _ in 0..5_000_000 {
                 x += 1
             }
             x
@@ -119,7 +119,6 @@ fn process() {
         println!("Thread finished with count={}",
            h.join().map_err(|_| "Could not join a thread!").unwrap());
     }
-    println!("done!");
 }
 ```
 
index aa1944a099335842116c1472f0ff82ed8ec3bee3..1848366498981dde6911449e63369550a609a10b 100644 (file)
@@ -102,8 +102,8 @@ println!("");
 This prints:
 
 ```text
-229, 191, 160, 231, 138, 172, 227, 131, 143, 227, 131, 129, 229, 133, 172, 
-忠, 犬, ハ, チ, 公, 
+229, 191, 160, 231, 138, 172, 227, 131, 143, 227, 131, 129, 229, 133, 172,
+忠, 犬, ハ, チ, 公,
 ```
 
 As you can see, there are more bytes than `char`s.
index 85b11d0b6b5eeb01b7002bf0a32d083e2b6eb6b3..b51ad8e087d22a995f550d2f15f79fc864cf17ba 100644 (file)
@@ -184,6 +184,8 @@ You can define a `struct` with no members at all:
 
 ```rust
 struct Electron;
+
+let x = Electron;
 ```
 
 Such a `struct` is called ‘unit-like’ because it resembles the empty
diff --git a/src/doc/trpl/syntax-index.md b/src/doc/trpl/syntax-index.md
new file mode 100644 (file)
index 0000000..7e03bb7
--- /dev/null
@@ -0,0 +1,229 @@
+% Syntax Index
+
+## Keywords
+
+* `as`: primitive casting.  See [Casting Between Types (`as`)].
+* `break`: break out of loop.  See [Loops (Ending Iteration Early)].
+* `const`: constant items.  See [`const` and `static`].
+* `continue`: continue to next loop iteration.  See [Loops (Ending Iteration Early)].
+* `crate`: external crate linkage.  See [Crates and Modules (Importing External Crates)].
+* `else`: fallback for `if` and `if let` constructs.  See [`if`], [`if let`].
+* `enum`: defining enumeration.  See [Enums].
+* `extern`: external crate, function, and variable linkage.  See [Crates and Modules (Importing External Crates)], [Foreign Function Interface].
+* `false`: boolean false literal.  See [Primitive Types (Booleans)].
+* `fn`: function definition and function pointer types.  See [Functions].
+* `for`: iterator loop, part of trait `impl` syntax, and higher-ranked lifetime syntax.  See [Loops (`for`)], [Method Syntax].
+* `if`: conditional branching.  See [`if`], [`if let`].
+* `impl`: inherent and trait implementation blocks.  See [Method Syntax].
+* `in`: part of `for` loop syntax.  See [Loops (`for`)].
+* `let`: variable binding.  See [Variable Bindings].
+* `loop`: unconditional, infinite loop.  See [Loops (`loop`)].
+* `match`: pattern matching.  See [Match].
+* `mod`: module declaration.  See [Crates and Modules (Defining Modules)].
+* `move`: part of closure syntax.  See [Closures (`move` closures)].
+* `mut`: denotes mutability in pointer types and pattern bindings.  See [Mutability].
+* `pub`: denotes public visibility in `struct` fields, `impl` blocks, and modules.  See [Crates and Modules (Exporting a Public Interface)].
+* `ref`: by-reference binding.  See [Patterns (`ref` and `ref mut`)].
+* `return`: return from function.  See [Functions (Early Returns)].
+* `Self`: implementor type alias.  See [Traits].
+* `self`: method subject.  See [Method Syntax (Method Calls)].
+* `static`: global variable.  See [`const` and `static` (`static`)].
+* `struct`: structure definition.  See [Structs].
+* `trait`: trait definition.  See [Traits].
+* `true`: boolean true literal.  See [Primitive Types (Booleans)].
+* `type`: type alias, and associated type definition.  See [`type` Aliases], [Associated Types].
+* `unsafe`: denotes unsafe code, functions, traits, and implementations.  See [Unsafe].
+* `use`: import symbols into scope.  See [Crates and Modules (Importing Modules with `use`)].
+* `where`: type constraint clauses.  See [Traits (`where` clause)].
+* `while`: conditional loop.  See [Loops (`while`)].
+
+## Operators and Symbols
+
+* `!` (`expr!(…)`, `expr!{…}`, `expr![…]`): denotes macro expansion.  See [Macros].
+* `!` (`!expr`): bitwise or logical complement.  Overloadable (`Not`).
+* `%` (`expr % expr`): arithmetic remainder.  Overloadable (`Rem`).
+* `%=` (`var %= expr`): arithmetic remainder & assignment.
+* `&` (`expr & expr`): bitwise and.  Overloadable (`BitAnd`).
+* `&` (`&expr`): borrow.  See [References and Borrowing].
+* `&` (`&type`, `&mut type`, `&'a type`, `&'a mut type`): borrowed pointer type.  See [References and Borrowing].
+* `&=` (`var &= expr`): bitwise and & assignment.
+* `&&` (`expr && expr`): logical and.
+* `*` (`expr * expr`): arithmetic multiplication.  Overloadable (`Mul`).
+* `*` (`*expr`): dereference.
+* `*` (`*const type`, `*mut type`): raw pointer.  See [Raw Pointers].
+* `*=` (`var *= expr`): arithmetic multiplication & assignment.
+* `+` (`expr + expr`): arithmetic addition.  Overloadable (`Add`).
+* `+` (`trait + trait`, `'a + trait`): compound type constraint.  See [Traits (Multiple Trait Bounds)].
+* `+=` (`var += expr`): arithmetic addition & assignment.
+* `,`: argument and element separator.  See [Attributes], [Functions], [Structs], [Generics], [Match], [Closures], [Crates and Modules (Importing Modules with `use`)].
+* `-` (`expr - expr`): arithmetic subtraction.  Overloadable (`Sub`).
+* `-` (`- expr`): arithmetic negation.  Overloadable (`Neg`).
+* `-=` (`var -= expr`): arithmetic subtraction & assignment.
+* `->` (`fn(…) -> type`, `|…| -> type`): function and closure return type.  See [Functions], [Closures].
+* `.` (`expr.ident`): member access.  See [Structs], [Method Syntax].
+* `..` (`..`, `expr..`, `..expr`, `expr..expr`): right-exclusive range literal.
+* `..` (`..expr`): struct literal update syntax.  See [Structs (Update syntax)].
+* `..` (`variant(x, ..)`, `struct_type { x, .. }`): "and the rest" pattern binding.  See [Patterns (Ignoring bindings)].
+* `...` (`expr ... expr`): inclusive range pattern.  See [Patterns (Ranges)].
+* `/` (`expr / expr`): arithmetic division.  Overloadable (`Div`).
+* `/=` (`var /= expr`): arithmetic division & assignment.
+* `:` (`pat: type`, `ident: type`): constraints.  See [Variable Bindings], [Functions], [Structs], [Traits].
+* `:` (`ident: expr`): struct field initializer.  See [Structs].
+* `:` (`'a: loop {…}`): loop label.  See [Loops (Loops Labels)].
+* `;`: statement and item terminator.
+* `;` (`[…; len]`): part of fixed-size array syntax.  See [Primitive Types (Arrays)].
+* `<<` (`expr << expr`): left-shift.  Overloadable (`Shl`).
+* `<<=` (`var <<= expr`): left-shift & assignment.
+* `<` (`expr < expr`): less-than comparison.  Overloadable (`Cmp`, `PartialCmp`).
+* `<=` (`var <= expr`): less-than or equal-to comparison.  Overloadable (`Cmp`, `PartialCmp`).
+* `=` (`var = expr`, `ident = type`): assignment/equivalence.  See [Variable Bindings], [`type` Aliases], generic parameter defaults.
+* `==` (`var == expr`): comparison.  Overloadable (`Eq`, `PartialEq`).
+* `=>` (`pat => expr`): part of match arm syntax.  See [Match].
+* `>` (`expr > expr`): greater-than comparison.  Overloadable (`Cmp`, `PartialCmp`).
+* `>=` (`var >= expr`): greater-than or equal-to comparison.  Overloadable (`Cmp`, `PartialCmp`).
+* `>>` (`expr >> expr`): right-shift.  Overloadable (`Shr`).
+* `>>=` (`var >>= expr`): right-shift & assignment.
+* `@` (`ident @ pat`): pattern binding.  See [Patterns (Bindings)].
+* `^` (`expr ^ expr`): bitwise exclusive or.  Overloadable (`BitXor`).
+* `^=` (`var ^= expr`): bitwise exclusive or & assignment.
+* `|` (`expr | expr`): bitwise or.  Overloadable (`BitOr`).
+* `|` (`pat | pat`): pattern alternatives.  See [Patterns (Multiple patterns)].
+* `|=` (`var |= expr`): bitwise or & assignment.
+* `||` (`expr || expr`): logical or.
+* `_`: "ignored" pattern binding.  See [Patterns (Ignoring bindings)].
+
+## Other Syntax
+
+<!-- Various bits of standalone stuff. -->
+
+* `'ident`: named lifetime or loop label.  See [Lifetimes], [Loops (Loops Labels)].
+* `…u8`, `…i32`, `…f64`, `…usize`, …: numeric literal of specific type.
+* `"…"`: string literal.  See [Strings].
+* `r"…"`, `r#"…"#`, `r##"…"##`, …: raw string literal.
+* `b"…"`: byte string literal.
+* `rb"…"`, `rb#"…"#`, `rb##"…"##`, …: raw byte string literal.
+* `'…'`: character literal.  See [Primitive Types (`char`)].
+* `b'…'`: ASCII byte literal.
+
+<!-- Path-related syntax -->
+
+* `ident::ident`: path.  See [Crates and Modules (Defining Modules)].
+* `::path`: path relative to the crate root (*i.e.* an explicitly absolute path).  See [Crates and Modules (Re-exporting with `pub use`)].
+* `self::path`: path relative to the current module (*i.e.* an explicitly relative path).  See [Crates and Modules (Re-exporting with `pub use`)].
+* `super::path`: path relative to the parent of the current module.  See [Crates and Modules (Re-exporting with `pub use`)].
+* `type::ident`: associated constants, functions, and types.  See [Associated Types].
+* `<type>::…`: associated item for a type which cannot be directly named (*e.g.* `<&T>::…`, `<[T]>::…`, *etc.*).  See [Associated Types].
+
+<!-- Generics -->
+
+* `path<…>` (*e.g.* `Vec<u8>`): specifies parameters to generic type *in a type*.  See [Generics].
+* `path::<…>`, `method::<…>` (*e.g.* `"42".parse::<i32>()`): specifies parameters to generic type, function, or method *in an expression*.
+* `fn ident<…> …`: define generic function.  See [Generics].
+* `struct ident<…> …`: define generic structure.  See [Generics].
+* `enum ident<…> …`: define generic enumeration.  See [Generics].
+* `impl<…> …`: define generic implementation.
+* `for<…> type`: higher-ranked lifetime bounds.
+* `type<ident=type>` (*e.g.* `Iterator<Item=T>`): a generic type where one or more associated types have specific assignments.  See [Associated Types].
+
+<!-- Constraints -->
+
+* `T: U`: generic parameter `T` constrained to types that implement `U`.  See [Traits].
+* `T: 'a`: generic type `T` must outlive lifetime `'a`.
+* `'b: 'a`: generic lifetime `'b` must outlive lifetime `'a`.
+* `T: ?Sized`: allow generic type parameter to be a dynamically-sized type.  See [Unsized Types (`?Sized`)].
+* `'a + trait`, `trait + trait`: compound type constraint.  See [Traits (Multiple Trait Bounds)].
+
+<!-- Macros and attributes -->
+
+* `#[meta]`: outer attribute.  See [Attributes].
+* `#![meta]`: inner attribute.  See [Attributes].
+* `$ident`: macro substitution.  See [Macros].
+* `$ident:kind`: macro capture.  See [Macros].
+* `$(…)…`: macro repetition.  See [Macros].
+
+<!-- Comments -->
+
+* `//`: line comment.  See [Comments].
+* `//!`: inner line doc comment.  See [Comments].
+* `///`: outer line doc comment.  See [Comments].
+* `/*…*/`: block comment.  See [Comments].
+* `/*!…*/`: inner block doc comment.  See [Comments].
+* `/**…*/`: outer block doc comment.  See [Comments].
+
+<!-- Various things involving parens and tuples -->
+
+* `()`: empty tuple (*a.k.a.* unit), both literal and type.
+* `(expr)`: parenthesized expression.
+* `(expr,)`: single-element tuple expression.  See [Primitive Types (Tuples)].
+* `(type,)`: single-element tuple type.  See [Primitive Types (Tuples)].
+* `(expr, …)`: tuple expression.  See [Primitive Types (Tuples)].
+* `(type, …)`: tuple type.  See [Primitive Types (Tuples)].
+* `expr(expr, …)`: function call expression.  Also used to initialize tuple `struct`s and tuple `enum` variants.  See [Functions].
+* `ident!(…)`, `ident!{…}`, `ident![…]`: macro invocation.  See [Macros].
+* `expr.0`, `expr.1`, …: tuple indexing.  See [Primitive Types (Tuple Indexing)].
+
+<!-- Bracey things -->
+
+* `{…}`: block expression.
+* `Type {…}`: `struct` literal.  See [Structs].
+
+<!-- Brackety things -->
+
+* `[…]`: array literal.  See [Primitive Types (Arrays)].
+* `[expr; len]`: array literal containing `len` copies of `expr`.  See [Primitive Types (Arrays)].
+* `[type; len]`: array type containing `len` instances of `type`.  See [Primitive Types (Arrays)].
+
+[`const` and `static` (`static`)]: const-and-static.html#static
+[`const` and `static`]: const-and-static.html
+[`if let`]: if-let.html
+[`if`]: if.html
+[`type` Aliases]: type-aliases.html
+[Associated Types]: associated-types.html
+[Attributes]: attributes.html
+[Casting Between Types (`as`)]: casting-between-types.html#as
+[Closures (`move` closures)]: closures.html#move-closures
+[Closures]: closures.html
+[Comments]: comments.html
+[Crates and Modules (Defining Modules)]: crates-and-modules.html#defining-modules
+[Crates and Modules (Exporting a Public Interface)]: crates-and-modules.html#exporting-a-public-interface
+[Crates and Modules (Importing External Crates)]: crates-and-modules.html#importing-external-crates
+[Crates and Modules (Importing Modules with `use`)]: crates-and-modules.html#importing-modules-with-use
+[Crates and Modules (Re-exporting with `pub use`)]: crates-and-modules.html#re-exporting-with-pub-use
+[Enums]: enums.html
+[Foreign Function Interface]: ffi.html
+[Functions (Early Returns)]: functions.html#early-returns
+[Functions]: functions.html
+[Generics]: generics.html
+[Lifetimes]: lifetimes.html
+[Loops (`for`)]: loops.html#for
+[Loops (`loop`)]: loops.html#loop
+[Loops (`while`)]: loops.html#while
+[Loops (Ending Iteration Early)]: loops.html#ending-iteration-early
+[Loops (Loops Labels)]: loops.html#loop-labels
+[Macros]: macros.html
+[Match]: match.html
+[Method Syntax (Method Calls)]: method-syntax.html#method-calls
+[Method Syntax]: method-syntax.html
+[Mutability]: mutability.html
+[Operators and Overloading]: operators-and-overloading.html
+[Patterns (`ref` and `ref mut`)]: patterns.html#ref-and-ref-mut
+[Patterns (Bindings)]: patterns.html#bindings
+[Patterns (Ignoring bindings)]: patterns.html#ignoring-bindings
+[Patterns (Multiple patterns)]: patterns.html#multiple-patterns
+[Patterns (Ranges)]: patterns.html#ranges
+[Primitive Types (`char`)]: primitive-types.html#char
+[Primitive Types (Arrays)]: primitive-types.html#arrays
+[Primitive Types (Booleans)]: primitive-types.html#booleans
+[Primitive Types (Tuple Indexing)]: primitive-types.html#tuple-indexing
+[Primitive Types (Tuples)]: primitive-types.html#tuples
+[Raw Pointers]: raw-pointers.html
+[References and Borrowing]: references-and-borrowing.html
+[Strings]: strings.html
+[Structs (Update syntax)]: structs.html#update-syntax
+[Structs]: structs.html
+[Traits (`where` clause)]: traits.html#where-clause
+[Traits (Multiple Trait Bounds)]: traits.html#multiple-trait-bounds
+[Traits]: traits.html
+[Unsafe]: unsafe.html
+[Unsized Types (`?Sized`)]: unsized-types.html#?sized
+[Variable Bindings]: variable-bindings.html
index 587f60343c344ade265760671c737a344bcd5a33..c6aeb86f7d32a3a06e7dbcff5491ff59f21a462a 100644 (file)
@@ -82,7 +82,7 @@ fn it_works() {
 ```
 
 `assert!` is a macro provided by Rust which takes one argument: if the argument
-is `true`, nothing happens. If the argument is false, it `panic!`s. Let's run
+is `true`, nothing happens. If the argument is `false`, it `panic!`s. Let's run
 our tests again:
 
 ```bash
@@ -289,7 +289,7 @@ running 0 tests
 test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
 ```
 
-The `--ignored` argument is an argument to the test binary, and not to cargo,
+The `--ignored` argument is an argument to the test binary, and not to Cargo,
 which is why the command is `cargo test -- --ignored`.
 
 # The `tests` module
@@ -367,7 +367,7 @@ It works!
 The current convention is to use the `tests` module to hold your "unit-style"
 tests. Anything that just tests one small bit of functionality makes sense to
 go here. But what about "integration-style" tests instead? For that, we have
-the `tests` directory
+the `tests` directory.
 
 # The `tests` directory
 
@@ -502,3 +502,8 @@ documentation tests: the `_0` is generated for the module test, and `add_two_0`
 for the function test. These will auto increment with names like `add_two_1` as
 you add more examples.
 
+We haven’t covered all of the details with writing documentation tests. For more,
+please see the [Documentation chapter](documentation.html)
+
+One final note: Tests *cannot* be run on a binary file. To see more on file arrangement see the [Crates and Modules](crates-and-modules.html) section.
+
index fb778b59a3d9385524b41df6c853cb802f182557..f30dacc485aae9d12bfdf76f9a39b1237209751c 100644 (file)
@@ -41,8 +41,8 @@ and just consider the local variables we’re allocating. So in this case, when
 This is automatically handled for you, as you can see; we didn’t have to write
 any special Rust code or anything.
 
-When the function is over, its stack frame gets deallocated. This happens
-automatically, we didn’t have to do anything special here.
+When the function exits, its stack frame gets deallocated. This happens
+automatically as well.
 
 That’s all there is for this simple program. The key thing to understand here
 is that stack allocation is very, very fast. Since we know all the local
@@ -217,18 +217,18 @@ on the heap. The actual value of the box is a structure which has a pointer to
 it allocates some memory for the heap, and puts `5` there. The memory now looks
 like this:
 
-| Address         | Name | Value            |
-|-----------------|------|------------------|
-| 2<sup>30</sup>  |      | 5                |
-| ...             | ...  | ...              |
-| 1               | y    | 42               |
-| 0               | x    | → 2<sup>30</sup> |
+| Address              | Name | Value                  |
+|----------------------|------|------------------------|
+| (2<sup>30</sup>) - 1 |      | 5                      |
+| ...                  | ...  | ...                    |
+| 1                    | y    | 42                     |
+| 0                    | x    | → (2<sup>30</sup>) - 1 |
 
-We have 2<sup>30</sup> in our hypothetical computer with 1GB of RAM. And since
+We have (2<sup>30</sup>) - 1 addresses in our hypothetical computer with 1GB of RAM. And since
 our stack grows from zero, the easiest place to allocate memory is from the
 other end. So our first value is at the highest place in memory. And the value
 of the struct at `x` has a [raw pointer][rawpointer] to the place we’ve
-allocated on the heap, so the value of `x` is 2<sup>30</sup>, the memory
+allocated on the heap, so the value of `x` is (2<sup>30</sup>) - 1, the memory
 location we’ve asked for.
 
 [rawpointer]: raw-pointers.html
@@ -244,18 +244,18 @@ layout of a program which has been running for a while now:
 
 | Address              | Name | Value                  |
 |----------------------|------|------------------------|
-| 2<sup>30</sup>       |      | 5                      |
-| (2<sup>30</sup>) - 1 |      |                        |
+| (2<sup>30</sup>) - 1 |      | 5                      |
 | (2<sup>30</sup>) - 2 |      |                        |
-| (2<sup>30</sup>) - 3 |      | 42                     |
+| (2<sup>30</sup>) - 3 |      |                        |
+| (2<sup>30</sup>) - 4 |      | 42                     |
 | ...                  | ...  | ...                    |
-| 3                    | y    | → (2<sup>30</sup>) - 3 |
+| 3                    | y    | → (2<sup>30</sup>) - 4 |
 | 2                    | y    | 42                     |
 | 1                    | y    | 42                     |
-| 0                    | x    | → 2<sup>30</sup>       |
+| 0                    | x    | → (2<sup>30</sup>) - 1 |
 
 In this case, we’ve allocated four things on the heap, but deallocated two of
-them. There’s a gap between 2<sup>30</sup> and (2<sup>30</sup>) - 3 which isn’t
+them. There’s a gap between (2<sup>30</sup>) - 1 and (2<sup>30</sup>) - 4 which isn’t
 currently being used. The specific details of how and why this happens depends
 on what kind of strategy you use to manage the heap. Different programs can use
 different ‘memory allocators’, which are libraries that manage this for you.
@@ -366,29 +366,29 @@ fn main() {
 
 First, we call `main()`:
 
-| Address         | Name | Value            |
-|-----------------|------|------------------|
-| 2<sup>30</sup>  |      | 20               |
-| ...             | ...  | ...              |
-| 2               | j    | → 0              |
-| 1               | i    | → 2<sup>30</sup> |
-| 0               | h    | 3                |
+| Address              | Name | Value                  |
+|----------------------|------|------------------------|
+| (2<sup>30</sup>) - 1 |      | 20                     |
+| ...                  | ...  | ...                    |
+| 2                    | j    | → 0                    |
+| 1                    | i    | → (2<sup>30</sup>) - 1 |
+| 0                    | h    | 3                      |
 
 We allocate memory for `j`, `i`, and `h`. `i` is on the heap, and so has a
 value pointing there.
 
 Next, at the end of `main()`, `foo()` gets called:
 
-| Address         | Name | Value           |
-|-----------------|------|-----------------|
-| 2<sup>30</sup>  |      | 20              |
-| ...             | ...  | ...             |
-| 5               | z    | → 4             |
-| 4               | y    | 10              |
-| 3               | x    | → 0             |
-| 2               | j    | → 0             |
-| 1               | i    | → 2<sup>30</sup>|
-| 0               | h    | 3               |
+| Address              | Name | Value                  |
+|----------------------|------|------------------------|
+| (2<sup>30</sup>) - 1 |      | 20                     |
+| ...                  | ...  | ...                    |
+| 5                    | z    | → 4                    |
+| 4                    | y    | 10                     |
+| 3                    | x    | → 0                    |
+| 2                    | j    | → 0                    |
+| 1                    | i    | → (2<sup>30</sup>) - 1 |
+| 0                    | h    | 3                      |
 
 Space gets allocated for `x`, `y`, and `z`. The argument `x` has the same value
 as `j`, since that’s what we passed it in. It’s a pointer to the `0` address,
@@ -396,42 +396,42 @@ since `j` points at `h`.
 
 Next, `foo()` calls `baz()`, passing `z`:
 
-| Address         | Name | Value            |
-|-----------------|------|------------------|
-| 2<sup>30</sup>  |      | 20               |
-| ...             | ...  | ...              |
-| 7               | g    | 100              |
-| 6               | f    | → 4              |
-| 5               | z    | → 4              |
-| 4               | y    | 10               |
-| 3               | x    | → 0              |
-| 2               | j    | → 0              |
-| 1               | i    | → 2<sup>30</sup> |
-| 0               | h    | 3                |
+| Address              | Name | Value                  |
+|----------------------|------|------------------------|
+| (2<sup>30</sup>) - 1 |      | 20                     |
+| ...                  | ...  | ...                    |
+| 7                    | g    | 100                    |
+| 6                    | f    | → 4                    |
+| 5                    | z    | → 4                    |
+| 4                    | y    | 10                     |
+| 3                    | x    | → 0                    |
+| 2                    | j    | → 0                    |
+| 1                    | i    | → (2<sup>30</sup>) - 1 |
+| 0                    | h    | 3                      |
 
 We’ve allocated memory for `f` and `g`. `baz()` is very short, so when it’s
 over, we get rid of its stack frame:
 
-| Address         | Name | Value            |
-|-----------------|------|------------------|
-| 2<sup>30</sup>  |      | 20               |
-| ...             | ...  | ...              |
-| 5               | z    | → 4              |
-| 4               | y    | 10               |
-| 3               | x    | → 0              |
-| 2               | j    | → 0              |
-| 1               | i    | → 2<sup>30</sup> |
-| 0               | h    | 3                |
+| Address              | Name | Value                  |
+|----------------------|------|------------------------|
+| (2<sup>30</sup>) - 1 |      | 20                     |
+| ...                  | ...  | ...                    |
+| 5                    | z    | → 4                    |
+| 4                    | y    | 10                     |
+| 3                    | x    | → 0                    |
+| 2                    | j    | → 0                    |
+| 1                    | i    | → (2<sup>30</sup>) - 1 |
+| 0                    | h    | 3                      |
 
 Next, `foo()` calls `bar()` with `x` and `z`:
 
 | Address              | Name | Value                  |
 |----------------------|------|------------------------|
-|  2<sup>30</sup>      |      | 20                     |
-| (2<sup>30</sup>) - 1 |      | 5                      |
+| (2<sup>30</sup>) - 1 |      | 20                     |
+| (2<sup>30</sup>) - 2 |      | 5                      |
 | ...                  | ...  | ...                    |
 | 10                   | e    | → 9                    |
-| 9                    | d    | → (2<sup>30</sup>) - 1 |
+| 9                    | d    | → (2<sup>30</sup>) - 2 |
 | 8                    | c    | 5                      |
 | 7                    | b    | → 4                    |
 | 6                    | a    | → 0                    |
@@ -439,24 +439,24 @@ Next, `foo()` calls `bar()` with `x` and `z`:
 | 4                    | y    | 10                     |
 | 3                    | x    | → 0                    |
 | 2                    | j    | → 0                    |
-| 1                    | i    | → 2<sup>30</sup>       |
+| 1                    | i    | → (2<sup>30</sup>) - 1 |
 | 0                    | h    | 3                      |
 
 We end up allocating another value on the heap, and so we have to subtract one
-from 2<sup>30</sup>. It’s easier to just write that than `1,073,741,823`. In any
+from (2<sup>30</sup>) - 1. It’s easier to just write that than `1,073,741,822`. In any
 case, we set up the variables as usual.
 
 At the end of `bar()`, it calls `baz()`:
 
 | Address              | Name | Value                  |
 |----------------------|------|------------------------|
-|  2<sup>30</sup>      |      | 20                     |
-| (2<sup>30</sup>) - 1 |      | 5                      |
+| (2<sup>30</sup>) - 1 |      | 20                     |
+| (2<sup>30</sup>) - 2 |      | 5                      |
 | ...                  | ...  | ...                    |
 | 12                   | g    | 100                    |
 | 11                   | f    | → 9                    |
 | 10                   | e    | → 9                    |
-| 9                    | d    | → (2<sup>30</sup>) - 1 |
+| 9                    | d    | → (2<sup>30</sup>) - 2 |
 | 8                    | c    | 5                      |
 | 7                    | b    | → 4                    |
 | 6                    | a    | → 0                    |
@@ -464,7 +464,7 @@ At the end of `bar()`, it calls `baz()`:
 | 4                    | y    | 10                     |
 | 3                    | x    | → 0                    |
 | 2                    | j    | → 0                    |
-| 1                    | i    | → 2<sup>30</sup>       |
+| 1                    | i    | → (2<sup>30</sup>) - 1 |
 | 0                    | h    | 3                      |
 
 With this, we’re at our deepest point! Whew! Congrats for following along this
@@ -474,11 +474,11 @@ After `baz()` is over, we get rid of `f` and `g`:
 
 | Address              | Name | Value                  |
 |----------------------|------|------------------------|
-|  2<sup>30</sup>      |      | 20                     |
-| (2<sup>30</sup>) - 1 |      | 5                      |
+| (2<sup>30</sup>) - 1 |      | 20                     |
+| (2<sup>30</sup>) - 2 |      | 5                      |
 | ...                  | ...  | ...                    |
 | 10                   | e    | → 9                    |
-| 9                    | d    | → (2<sup>30</sup>) - 1 |
+| 9                    | d    | → (2<sup>30</sup>) - 2 |
 | 8                    | c    | 5                      |
 | 7                    | b    | → 4                    |
 | 6                    | a    | → 0                    |
@@ -486,32 +486,32 @@ After `baz()` is over, we get rid of `f` and `g`:
 | 4                    | y    | 10                     |
 | 3                    | x    | → 0                    |
 | 2                    | j    | → 0                    |
-| 1                    | i    | → 2<sup>30</sup>       |
+| 1                    | i    | → (2<sup>30</sup>) - 1 |
 | 0                    | h    | 3                      |
 
 Next, we return from `bar()`. `d` in this case is a `Box<T>`, so it also frees
-what it points to: (2<sup>30</sup>) - 1.
-
-| Address         | Name | Value            |
-|-----------------|------|------------------|
-|  2<sup>30</sup> |      | 20               |
-| ...             | ...  | ...              |
-| 5               | z    | → 4              |
-| 4               | y    | 10               |
-| 3               | x    | → 0              |
-| 2               | j    | → 0              |
-| 1               | i    | → 2<sup>30</sup> |
-| 0               | h    | 3                |
+what it points to: (2<sup>30</sup>) - 2.
+
+| Address              | Name | Value                  |
+|----------------------|------|------------------------|
+| (2<sup>30</sup>) - 1 |      | 20                     |
+| ...                  | ...  | ...                    |
+| 5                    | z    | → 4                    |
+| 4                    | y    | 10                     |
+| 3                    | x    | → 0                    |
+| 2                    | j    | → 0                    |
+| 1                    | i    | → (2<sup>30</sup>) - 1 |
+| 0                    | h    | 3                      |
 
 And after that, `foo()` returns:
 
-| Address         | Name | Value            |
-|-----------------|------|------------------|
-|  2<sup>30</sup> |      | 20               |
-| ...             | ...  | ...              |
-| 2               | j    | → 0              |
-| 1               | i    | → 2<sup>30</sup> |
-| 0               | h    | 3                |
+| Address              | Name | Value                  |
+|----------------------|------|------------------------|
+| (2<sup>30</sup>) - 1 |      | 20                     |
+| ...                  | ...  | ...                    |
+| 2                    | j    | → 0                    |
+| 1                    | i    | → (2<sup>30</sup>) - 1 |
+| 0                    | h    | 3                      |
 
 And then, finally, `main()`, which cleans the rest up. When `i` is `Drop`ped,
 it will clean up the last of the heap too.
index 0870a6ef3414739aba63930b1f8269a6f0a7e07d..7b6d0b730a30462b137295e82b8ea351a82e7f88 100644 (file)
@@ -47,12 +47,14 @@ As you can see, the `trait` block looks very similar to the `impl` block,
 but we don’t define a body, just a type signature. When we `impl` a trait,
 we use `impl Trait for Item`, rather than just `impl Item`.
 
-## Traits bounds for generic functions
+## Trait bounds on generic functions
 
 Traits are useful because they allow a type to make certain promises about its
-behavior. Generic functions can exploit this to constrain the types they
+behavior. Generic functions can exploit this to constrain, or [bound][bounds], the types they
 accept. Consider this function, which does not compile:
 
+[bounds]: glossary.html#bounds
+
 ```rust,ignore
 fn print_area<T>(shape: T) {
     println!("This shape has an area of {}", shape.area());
@@ -66,7 +68,7 @@ error: no method named `area` found for type `T` in the current scope
 ```
 
 Because `T` can be any type, we can’t be sure that it implements the `area`
-method. But we can add a ‘trait constraint’ to our generic `T`, ensuring
+method. But we can add a trait bound to our generic `T`, ensuring
 that it does:
 
 ```rust
@@ -155,10 +157,10 @@ We get a compile-time error:
 error: the trait `HasArea` is not implemented for the type `_` [E0277]
 ```
 
-## Traits bounds for generic structs
+## Trait bounds on generic structs
 
-Your generic structs can also benefit from trait constraints. All you need to
-do is append the constraint when you declare type parameters. Here is a new
+Your generic structs can also benefit from trait bounds. All you need to
+do is append the bound when you declare type parameters. Here is a new
 type `Rectangle<T>` and its operation `is_square()`:
 
 ```rust
@@ -492,3 +494,32 @@ If we forget to implement `Foo`, Rust will tell us:
 ```text
 error: the trait `main::Foo` is not implemented for the type `main::Baz` [E0277]
 ```
+
+# Deriving
+
+Implementing traits like `Debug` and `Default` over and over again can become
+quite tedious. For that reason, Rust provides an [attribute][attributes] that
+allows you to let Rust automatically implement traits for you:
+
+```rust
+#[derive(Debug)]
+struct Foo;
+
+fn main() {
+    println!("{:?}", Foo);
+}
+```
+
+[attributes]: attributes.html
+
+However, deriving is limited to a certain set of traits:
+
+- [`Clone`](../core/clone/trait.Clone.html)
+- [`Copy`](../core/marker/trait.Copy.html)
+- [`Debug`](../core/fmt/trait.Debug.html)
+- [`Default`](../core/default/trait.Default.html)
+- [`Eq`](../core/cmp/trait.Eq.html)
+- [`Hash`](../core/hash/trait.Hash.html)
+- [`Ord`](../core/cmp/trait.Ord.html)
+- [`PartialEq`](../core/cmp/trait.PartialEq.html)
+- [`PartialOrd`](../core/cmp/trait.PartialOrd.html)
index 2166c046897f0a56da8c299dbd95a737a3dda291..f3a5d1dd886c82b86538372b525f35da1c8ebff7 100644 (file)
@@ -1,7 +1,8 @@
 % Variable Bindings
 
 Virtually every non-'Hello World’ Rust program uses *variable bindings*. They
-look like this:
+bind some value to a name, so it can be used later. `let` is
+used to introduce a binding, just like this:
 
 ```rust
 fn main() {
@@ -13,10 +14,12 @@ Putting `fn main() {` in each example is a bit tedious, so we’ll leave that ou
 in the future. If you’re following along, make sure to edit your `main()`
 function, rather than leaving it off. Otherwise, you’ll get an error.
 
-In many languages, this is called a *variable*, but Rust’s variable bindings
-have a few tricks up their sleeves. For example the left-hand side of a `let`
-expression is a ‘[pattern][pattern]’, not just a variable name. This means we
-can do things like:
+# Patterns
+
+In many languages, a variable binding would be called a *variable*, but Rust’s
+variable bindings have a few tricks up their sleeves. For example the
+left-hand side of a `let` expression is a ‘[pattern][pattern]’, not just a
+variable name. This means we can do things like:
 
 ```rust
 let (x, y) = (1, 2);
@@ -29,6 +32,8 @@ of our minds as we go forward.
 
 [pattern]: patterns.html
 
+# Type annotations
+
 Rust is a statically typed language, which means that we specify our types up
 front, and they’re checked at compile time. So why does our first example
 compile? Well, Rust has this thing called ‘type inference’. If it can figure
@@ -63,6 +68,8 @@ Note the similarities between this annotation and the syntax you use with
 occasionally include them to help you understand what the types that Rust
 infers are.
 
+# Mutability
+
 By default, bindings are *immutable*. This code will not compile:
 
 ```rust,ignore
@@ -97,9 +104,11 @@ out of the scope of this guide. In general, you can often avoid explicit
 mutation, and so it is preferable in Rust. That said, sometimes, mutation is
 what you need, so it’s not verboten.
 
-Let’s get back to bindings. Rust variable bindings have one more aspect that
-differs from other languages: bindings are required to be initialized with a
-value before you're allowed to use them.
+# Initializing bindings
+
+Rust variable bindings have one more aspect that differs from other languages:
+bindings are required to be initialized with a value before you're allowed to
+use them.
 
 Let’s try it out. Change your `src/main.rs` file to look like this:
 
@@ -167,3 +176,77 @@ For now, we'll just stick to the default: integers aren't very complicated to
 print.
 
 [format]: ../std/fmt/index.html
+
+# Scope and shadowing
+
+Let’s get back to bindings. Variable bindings have a scope - they are
+constrained to live in a block they were defined in. A block is a collection
+of statements enclosed by `{` and `}`. Function definitions are also blocks!
+In the following example we define two variable bindings, `x` and `y`, which
+live in different blocks. `x` can be accessed from inside the `fn main() {}`
+block, while `y` can be accessed only from inside the inner block:
+
+```rust,ignore
+fn main() {
+    let x: i32 = 17;
+    {
+        let y: i32 = 3;
+        println!("The value of x is {} and value of y is {}", x, y);
+    }
+    println!("The value of x is {} and value of y is {}", x, y); // This won't work
+}
+```
+
+The first `println!` would print "The value of x is 17 and the value of y is
+3", but this example cannot be compiled successfully, because the second
+`println!` cannot access the value of `y`, since it is not in scope anymore.
+Instead we get this error:
+
+```bash
+$ cargo build
+   Compiling hello v0.1.0 (file:///home/you/projects/hello_world)
+main.rs:7:62: 7:63 error: unresolved name `y`. Did you mean `x`? [E0425]
+main.rs:7     println!("The value of x is {} and value of y is {}", x, y); // This won't work
+                                                                       ^
+note: in expansion of format_args!
+<std macros>:2:25: 2:56 note: expansion site
+<std macros>:1:1: 2:62 note: in expansion of print!
+<std macros>:3:1: 3:54 note: expansion site
+<std macros>:1:1: 3:58 note: in expansion of println!
+main.rs:7:5: 7:65 note: expansion site
+main.rs:7:62: 7:63 help: run `rustc --explain E0425` to see a detailed explanation
+error: aborting due to previous error
+Could not compile `hello`.
+
+To learn more, run the command again with --verbose.
+```
+
+Additionally, variable bindings can be shadowed. This means that a later
+variable binding with the same name as another binding, that's currently in
+scope, will override the previous binding.
+
+```rust
+let x: i32 = 8;
+{
+    println!("{}", x); // Prints "8"
+    let x = 12;
+    println!("{}", x); // Prints "12"
+}
+println!("{}", x); // Prints "8"
+let x =  42;
+println!("{}", x); // Prints "42"
+```
+
+Shadowing and mutable bindings may appear as two sides of the same coin, but
+they are two distinct concepts that can't always be used interchangeably. For
+one, shadowing enables us to rebind a name to a value of a different type. It
+is also possible to change the mutability of a binding.
+
+```rust
+let mut x: i32 = 1;
+x = 7;
+let x = x; // x is now immutable and is bound to 7
+
+let y = 4;
+let y = "I can also be bound to text!"; // y is now of a different type
+```
index d8b894a2f6522ba45b78b6debf369e3b4edbd587..7b826f08ae6fbb34c9ee1ed47b482ef813b3270a 100644 (file)
@@ -32,6 +32,35 @@ println!("The third element of v is {}", v[2]);
 
 The indices count from `0`, so the third element is `v[2]`.
 
+It’s also important to note that you must index with the `usize` type:
+
+```ignore
+let v = vec![1, 2, 3, 4, 5];
+
+let i: usize = 0;
+let j: i32 = 0;
+
+// works
+v[i];
+
+// doesn’t
+v[j];
+```
+
+Indexing with a non-`usize` type gives an error that looks like this:
+
+```text
+error: the trait `core::ops::Index<i32>` is not implemented for the type
+`collections::vec::Vec<_>` [E0277]
+v[j];
+^~~~
+note: the type `collections::vec::Vec<_>` cannot be indexed by `i32`
+error: aborting due to previous error
+```
+
+There’s a lot of punctuation in that message, but the core of it makes sense:
+you cannot index with an `i32`.
+
 ## Iterating
 
 Once you have a vector, you can iterate through its elements with `for`. There
index c5c58bb49ac361f34df30451b9badd02450acab9..e74652d85d788accd12f4e09660da3a9ea33cad8 100644 (file)
@@ -17,4 +17,6 @@ extern crate rustdoc as this;
 #[cfg(rustc)]
 extern crate rustc_driver as this;
 
-fn main() { this::main() }
+fn main() {
+    this::main()
+}
index cbb67014e276025f4e3e3eb1473cbf642ff8a67f..4b10b02f2d40725df318604d6cf1c0ba90daf28e 100644 (file)
@@ -34,10 +34,7 @@ fn load_all_errors(metadata_dir: &Path) -> Result<ErrorMetadataMap, Box<Error>>
         let path = try!(entry).path();
 
         let mut metadata_str = String::new();
-        try!(
-            File::open(&path).and_then(|mut f|
-            f.read_to_string(&mut metadata_str))
-        );
+        try!(File::open(&path).and_then(|mut f| f.read_to_string(&mut metadata_str)));
 
         let some_errors: ErrorMetadataMap = try!(json::decode(&metadata_str));
 
@@ -78,24 +75,23 @@ r##"<!DOCTYPE html>
         // Enclose each error in a div so they can be shown/hidden en masse.
         let desc_desc = match info.description {
             Some(_) => "error-described",
-            None => "error-undescribed"
+            None => "error-undescribed",
         };
         let use_desc = match info.use_site {
             Some(_) => "error-used",
-            None => "error-unused"
+            None => "error-unused",
         };
         try!(write!(&mut output_file, "<div class=\"{} {}\">", desc_desc, use_desc));
 
         // Error title (with self-link).
         try!(write!(&mut output_file,
-            "<h2 id=\"{0}\" class=\"section-header\"><a href=\"#{0}\">{0}</a></h2>\n",
-            err_code
-        ));
+                    "<h2 id=\"{0}\" class=\"section-header\"><a href=\"#{0}\">{0}</a></h2>\n",
+                    err_code));
 
         // Description rendered as markdown.
         match info.description {
             Some(ref desc) => try!(write!(&mut output_file, "{}", Markdown(desc))),
-            None => try!(write!(&mut output_file, "<p>No description.</p>\n"))
+            None => try!(write!(&mut output_file, "<p>No description.</p>\n")),
         }
 
         try!(write!(&mut output_file, "</div>\n"));
index a8a62358d3afe41f578c2a7ca2701a7db295f717..790fc8942873e29c8876cf85476ac1cfaa57cc58 100755 (executable)
@@ -119,7 +119,7 @@ for (trait, supers, errs) in [('Clone', [], 1),
                               ('PartialOrd', ['PartialEq'], 8),
                               ('Eq', ['PartialEq'], 1),
                               ('Ord', ['Eq', 'PartialOrd', 'PartialEq'], 1),
-                              ('Show', [], 1),
+                              ('Debug', [], 1),
                               ('Hash', [], 1)]:
     traits[trait] = (ALL, supers, errs)
 
index 04bf81a96aaf3ab09d6389712645c05228e6ddf2..c2958caddc40098e22d677c9e282fe73a74f0c83 100644 (file)
@@ -12,6 +12,7 @@ import subprocess
 import os
 import sys
 
+target_triple = sys.argv[14]
 
 def normalize_path(v):
     """msys1/msys2 automatically converts `/abs/path1:/abs/path2` into
@@ -22,8 +23,11 @@ def normalize_path(v):
     windows paths so it is really error-prone. revert it for peace."""
     v = v.replace('\\', '/')
     # c:/path -> /c/path
-    if ':/' in v:
-        v = '/' + v.replace(':/', '/')
+    # "c:/path" -> "/c/path"
+    start = v.find(':/')
+    while start != -1:
+        v = v[:start - 1] + '/' + v[start - 1:start] + v[start + 1:]
+        start = v.find(':/')
     return v
 
 
@@ -50,6 +54,10 @@ putenv('TARGET_RPATH_DIR', os.path.abspath(sys.argv[11]))
 putenv('RUST_BUILD_STAGE', sys.argv[12])
 putenv('S', os.path.abspath(sys.argv[13]))
 putenv('PYTHON', sys.executable)
+os.putenv('TARGET', target_triple)
+
+if 'msvc' in target_triple:
+    os.putenv('IS_MSVC', '1')
 
 if filt not in sys.argv[1]:
     sys.exit(0)
index 1cc65406b2c005076292a8255f5b59db96a22cc3..215fa1cdd1bb757ac0bb06377a92ebf8a29ec182 100644 (file)
@@ -17,6 +17,7 @@ f = open(sys.argv[1], 'wb')
 components = sys.argv[2].split() # splits on whitespace
 enable_static = sys.argv[3]
 llvm_config = sys.argv[4]
+stdcpp_name = sys.argv[5]
 
 f.write("""// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
@@ -77,7 +78,7 @@ for lib in out.strip().split(' '):
 out = run([llvm_config, '--cxxflags'])
 if enable_static == '1':
     assert('stdlib=libc++' not in out)
-    f.write("#[link(name = \"stdc++\", kind = \"static\")]\n")
+    f.write("#[link(name = \"" + stdcpp_name + "\", kind = \"static\")]\n")
 else:
     # Note that we use `cfg_attr` here because on MSVC the C++ standard library
     # is not c++ or stdc++, but rather the linker takes care of linking the
@@ -85,7 +86,7 @@ else:
     if 'stdlib=libc++' in out:
         f.write("#[cfg_attr(not(target_env = \"msvc\"), link(name = \"c++\"))]\n")
     else:
-        f.write("#[cfg_attr(not(target_env = \"msvc\"), link(name = \"stdc++\"))]\n")
+        f.write("#[cfg_attr(not(target_env = \"msvc\"), link(name = \"" + stdcpp_name + "\"))]\n")
 
 # Attach everything to an extern block
 f.write("extern {}\n")
index 17a1b769bd63fa328b96a9c47fec44692690cd4b..27af63a5876bc2c208d6405e3d31799d50da50c5 100644 (file)
@@ -71,7 +71,7 @@ The output on stdout is treated as (f64, f32, decimal) record, encoded thusly:
 
 Incomplete records are an error. Not-a-Number bit patterns are invalid too.
 
-The tests run serially but the validaition for a a single test is parallelized
+The tests run serially but the validation for a single test is parallelized
 with ``multiprocessing``. Each test is launched as a subprocess.
 One thread supervises it: Accepts and enqueues records to validate, observe
 stderr, and waits for the process to exit. A set of worker processes perform
index 2c14741947032ce56ebd4d95737e217e20656cb9..3eeb1ac4723dbc975dfa21631c70ad8adc91eb4f 100755 (executable)
@@ -313,14 +313,19 @@ def escape_char(c):
 
 def emit_bsearch_range_table(f):
     f.write("""
-fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool {
+fn bsearch_range_table(c: char, r: &'static [(char, char)]) -> bool {
     use core::cmp::Ordering::{Equal, Less, Greater};
     use core::slice::SliceExt;
-    r.binary_search_by(|&(lo,hi)| {
-        if lo <= c && c <= hi { Equal }
-        else if hi < c { Less }
-        else { Greater }
-    }).is_ok()
+    r.binary_search_by(|&(lo, hi)| {
+         if lo <= c && c <= hi {
+             Equal
+         } else if hi < c {
+             Less
+         } else {
+             Greater
+         }
+     })
+     .is_ok()
 }\n
 """)
 
index 8259d8ea677402e377107e02505629fec64a2a50..ffdc2b03970d198fb977be4ea50473ca238253c0 100644 (file)
@@ -1 +1 @@
-0.12.0-13461-g8ab8581f6921bc7a8e3fa4defffd2814372dcb15
+0.12.0-14610-g3d7cd77e442ce34eaac8a176ae8be17669498ebc
index 78821403de0116cf2a5700cb1b2e6de1f2f391b3..33ca80ba3725967c3a327e4332714a5bb655ec24 100644 (file)
@@ -79,9 +79,8 @@ use core::cmp::Ordering;
 use core::mem::{align_of_val, size_of_val};
 use core::intrinsics::{drop_in_place, abort};
 use core::mem;
-use core::nonzero::NonZero;
 use core::ops::{Deref, CoerceUnsized};
-use core::ptr;
+use core::ptr::{self, Shared};
 use core::marker::Unsize;
 use core::hash::{Hash, Hasher};
 use core::{usize, isize};
@@ -93,7 +92,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
 ///
 /// # Examples
 ///
-/// In this example, a large vector of floats is shared between several threads.
+/// In this example, a large vector is shared between several threads.
 /// With simple pipes, without `Arc`, a copy would have to be made for each
 /// thread.
 ///
@@ -124,12 +123,13 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
 pub struct Arc<T: ?Sized> {
     // FIXME #12808: strange name to try to avoid interfering with
     // field accesses of the contained type via Deref
-    _ptr: NonZero<*mut ArcInner<T>>,
+    _ptr: Shared<ArcInner<T>>,
 }
 
 unsafe impl<T: ?Sized + Sync + Send> Send for Arc<T> { }
 unsafe impl<T: ?Sized + Sync + Send> Sync for Arc<T> { }
 
+#[cfg(not(stage0))] // remove cfg after new snapshot
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
 
 /// A weak pointer to an `Arc`.
@@ -141,12 +141,13 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Arc<U>> for Arc<T> {}
 pub struct Weak<T: ?Sized> {
     // FIXME #12808: strange name to try to avoid interfering with
     // field accesses of the contained type via Deref
-    _ptr: NonZero<*mut ArcInner<T>>,
+    _ptr: Shared<ArcInner<T>>,
 }
 
 unsafe impl<T: ?Sized + Sync + Send> Send for Weak<T> { }
 unsafe impl<T: ?Sized + Sync + Send> Sync for Weak<T> { }
 
+#[cfg(not(stage0))] // remove cfg after new snapshot
 impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -190,7 +191,7 @@ impl<T> Arc<T> {
             weak: atomic::AtomicUsize::new(1),
             data: data,
         };
-        Arc { _ptr: unsafe { NonZero::new(Box::into_raw(x)) } }
+        Arc { _ptr: unsafe { Shared::new(Box::into_raw(x)) } }
     }
 
     /// Unwraps the contained value if the `Arc<T>` has only one strong reference.
@@ -214,7 +215,9 @@ impl<T> Arc<T> {
     #[stable(feature = "arc_unique", since = "1.4.0")]
     pub fn try_unwrap(this: Self) -> Result<T, Self> {
         // See `drop` for why all these atomics are like this
-        if this.inner().strong.compare_and_swap(1, 0, Release) != 1 { return Err(this) }
+        if this.inner().strong.compare_and_swap(1, 0, Release) != 1 {
+            return Err(this)
+        }
 
         atomic::fence(Acquire);
 
@@ -251,7 +254,9 @@ impl<T: ?Sized> Arc<T> {
             let cur = this.inner().weak.load(Relaxed);
 
             // check if the weak counter is currently "locked"; if so, spin.
-            if cur == usize::MAX { continue }
+            if cur == usize::MAX {
+                continue
+            }
 
             // NOTE: this code currently ignores the possibility of overflow
             // into usize::MAX; in general both Rc and Arc need to be adjusted
@@ -348,7 +353,9 @@ impl<T: ?Sized> Clone for Arc<T> {
         // We abort because such a program is incredibly degenerate, and we
         // don't care to support it.
         if old_size > MAX_REFCOUNT {
-            unsafe { abort(); }
+            unsafe {
+                abort();
+            }
         }
 
         Arc { _ptr: self._ptr }
@@ -542,6 +549,7 @@ impl<T: ?Sized> Drop for Arc<T> {
     ///
     /// } // implicit drop
     /// ```
+    #[unsafe_destructor_blind_to_params]
     #[inline]
     fn drop(&mut self) {
         // This structure has #[unsafe_no_drop_flag], so this drop glue may run
@@ -556,7 +564,9 @@ impl<T: ?Sized> Drop for Arc<T> {
         // Because `fetch_sub` is already atomic, we do not need to synchronize
         // with other threads unless we are going to delete the object. This
         // same logic applies to the below `fetch_sub` to the `weak` count.
-        if self.inner().strong.fetch_sub(1, Release) != 1 { return }
+        if self.inner().strong.fetch_sub(1, Release) != 1 {
+            return
+        }
 
         // This fence is needed to prevent reordering of use of the data and
         // deletion of the data.  Because it is marked `Release`, the decreasing
@@ -578,7 +588,7 @@ impl<T: ?Sized> Drop for Arc<T> {
         atomic::fence(Acquire);
 
         unsafe {
-            self.drop_slow()
+            self.drop_slow();
         }
     }
 }
@@ -613,11 +623,15 @@ impl<T: ?Sized> Weak<T> {
             // "stale" read of 0 is fine), and any other value is
             // confirmed via the CAS below.
             let n = inner.strong.load(Relaxed);
-            if n == 0 { return None }
+            if n == 0 {
+                return None
+            }
 
             // Relaxed is valid for the same reason it is on Arc's Clone impl
             let old = inner.strong.compare_and_swap(n, n + 1, Relaxed);
-            if old == n { return Some(Arc { _ptr: self._ptr }) }
+            if old == n {
+                return Some(Arc { _ptr: self._ptr })
+            }
         }
     }
 
@@ -653,7 +667,9 @@ impl<T: ?Sized> Clone for Weak<T> {
 
         // See comments in Arc::clone() for why we do this (for mem::forget).
         if old_size > MAX_REFCOUNT {
-            unsafe { abort(); }
+            unsafe {
+                abort();
+            }
         }
 
         return Weak { _ptr: self._ptr }
@@ -705,9 +721,7 @@ impl<T: ?Sized> Drop for Weak<T> {
         // ref, which can only happen after the lock is released.
         if self.inner().weak.fetch_sub(1, Release) == 1 {
             atomic::fence(Acquire);
-            unsafe { deallocate(ptr as *mut u8,
-                                size_of_val(&*ptr),
-                                align_of_val(&*ptr)) }
+            unsafe { deallocate(ptr as *mut u8, size_of_val(&*ptr), align_of_val(&*ptr)) }
         }
     }
 }
@@ -727,7 +741,9 @@ impl<T: ?Sized + PartialEq> PartialEq for Arc<T> {
     ///
     /// five == Arc::new(5);
     /// ```
-    fn eq(&self, other: &Arc<T>) -> bool { *(*self) == *(*other) }
+    fn eq(&self, other: &Arc<T>) -> bool {
+        *(*self) == *(*other)
+    }
 
     /// Inequality for two `Arc<T>`s.
     ///
@@ -742,7 +758,9 @@ impl<T: ?Sized + PartialEq> PartialEq for Arc<T> {
     ///
     /// five != Arc::new(5);
     /// ```
-    fn ne(&self, other: &Arc<T>) -> bool { *(*self) != *(*other) }
+    fn ne(&self, other: &Arc<T>) -> bool {
+        *(*self) != *(*other)
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> {
@@ -776,7 +794,9 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> {
     ///
     /// five < Arc::new(5);
     /// ```
-    fn lt(&self, other: &Arc<T>) -> bool { *(*self) < *(*other) }
+    fn lt(&self, other: &Arc<T>) -> bool {
+        *(*self) < *(*other)
+    }
 
     /// 'Less-than or equal to' comparison for two `Arc<T>`s.
     ///
@@ -791,7 +811,9 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> {
     ///
     /// five <= Arc::new(5);
     /// ```
-    fn le(&self, other: &Arc<T>) -> bool { *(*self) <= *(*other) }
+    fn le(&self, other: &Arc<T>) -> bool {
+        *(*self) <= *(*other)
+    }
 
     /// Greater-than comparison for two `Arc<T>`s.
     ///
@@ -806,7 +828,9 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> {
     ///
     /// five > Arc::new(5);
     /// ```
-    fn gt(&self, other: &Arc<T>) -> bool { *(*self) > *(*other) }
+    fn gt(&self, other: &Arc<T>) -> bool {
+        *(*self) > *(*other)
+    }
 
     /// 'Greater-than or equal to' comparison for two `Arc<T>`s.
     ///
@@ -821,11 +845,15 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Arc<T> {
     ///
     /// five >= Arc::new(5);
     /// ```
-    fn ge(&self, other: &Arc<T>) -> bool { *(*self) >= *(*other) }
+    fn ge(&self, other: &Arc<T>) -> bool {
+        *(*self) >= *(*other)
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + Ord> Ord for Arc<T> {
-    fn cmp(&self, other: &Arc<T>) -> Ordering { (**self).cmp(&**other) }
+    fn cmp(&self, other: &Arc<T>) -> Ordering {
+        (**self).cmp(&**other)
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + Eq> Eq for Arc<T> {}
@@ -854,7 +882,9 @@ impl<T> fmt::Pointer for Arc<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Default> Default for Arc<T> {
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn default() -> Arc<T> { Arc::new(Default::default()) }
+    fn default() -> Arc<T> {
+        Arc::new(Default::default())
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1015,7 +1045,7 @@ mod tests {
     #[test]
     fn weak_self_cyclic() {
         struct Cycle {
-            x: Mutex<Option<Weak<Cycle>>>
+            x: Mutex<Option<Weak<Cycle>>>,
         }
 
         let a = Arc::new(Cycle { x: Mutex::new(None) });
@@ -1095,7 +1125,9 @@ mod tests {
 
     // Make sure deriving works with Arc<T>
     #[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)]
-    struct Foo { inner: Arc<i32> }
+    struct Foo {
+        inner: Arc<i32>,
+    }
 
     #[test]
     fn test_unsized() {
@@ -1108,5 +1140,14 @@ mod tests {
 }
 
 impl<T: ?Sized> borrow::Borrow<T> for Arc<T> {
-    fn borrow(&self) -> &T { &**self }
+    fn borrow(&self) -> &T {
+        &**self
+    }
+}
+
+#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")]
+impl<T: ?Sized> AsRef<T> for Arc<T> {
+    fn as_ref(&self) -> &T {
+        &**self
+    }
 }
index 4293b4765e127777fb6614bae1b2f77c835f28cd..4783b4339dac3af888633b490e6c2cea36b88e2c 100644 (file)
@@ -66,7 +66,7 @@ use core::mem;
 use core::ops::{CoerceUnsized, Deref, DerefMut};
 use core::ops::{Placer, Boxed, Place, InPlace, BoxPlace};
 use core::ptr::{self, Unique};
-use core::raw::{TraitObject};
+use core::raw::TraitObject;
 
 /// A value that represents the heap. This is the default place that the `box`
 /// keyword allocates into when no place is supplied.
@@ -80,11 +80,10 @@ use core::raw::{TraitObject};
 /// use std::boxed::HEAP;
 ///
 /// fn main() {
-///     let foo = box(HEAP) 5;
+///     let foo: Box<i32> = in HEAP { 5 };
 ///     let foo = box 5;
 /// }
 /// ```
-#[lang = "exchange_heap"]
 #[unstable(feature = "box_heap",
            reason = "may be renamed; uncertain about custom allocator design",
            issue = "27779")]
@@ -96,7 +95,9 @@ pub const HEAP: ExchangeHeapSingleton =
            reason = "may be renamed; uncertain about custom allocator design",
            issue = "27779")]
 #[derive(Copy, Clone)]
-pub struct ExchangeHeapSingleton { _force_singleton: () }
+pub struct ExchangeHeapSingleton {
+    _force_singleton: (),
+}
 
 /// A pointer type for heap allocation.
 ///
@@ -127,7 +128,7 @@ pub struct Box<T: ?Sized>(Unique<T>);
 #[unstable(feature = "placement_in",
            reason = "placement box design is still being worked out.",
            issue = "27779")]
-pub struct IntermediateBox<T: ?Sized>{
+pub struct IntermediateBox<T: ?Sized> {
     ptr: *mut u8,
     size: usize,
     align: usize,
@@ -136,7 +137,7 @@ pub struct IntermediateBox<T: ?Sized>{
 
 impl<T> Place<T> for IntermediateBox<T> {
     fn pointer(&mut self) -> *mut T {
-        unsafe { ::core::mem::transmute(self.ptr) }
+        self.ptr as *mut T
     }
 }
 
@@ -153,31 +154,40 @@ fn make_place<T>() -> IntermediateBox<T> {
     let p = if size == 0 {
         heap::EMPTY as *mut u8
     } else {
-        let p = unsafe {
-            heap::allocate(size, align)
-        };
+        let p = unsafe { heap::allocate(size, align) };
         if p.is_null() {
             panic!("Box make_place allocation failure.");
         }
         p
     };
 
-    IntermediateBox { ptr: p, size: size, align: align, marker: marker::PhantomData }
+    IntermediateBox {
+        ptr: p,
+        size: size,
+        align: align,
+        marker: marker::PhantomData,
+    }
 }
 
 impl<T> BoxPlace<T> for IntermediateBox<T> {
-    fn make_place() -> IntermediateBox<T> { make_place() }
+    fn make_place() -> IntermediateBox<T> {
+        make_place()
+    }
 }
 
 impl<T> InPlace<T> for IntermediateBox<T> {
     type Owner = Box<T>;
-    unsafe fn finalize(self) -> Box<T> { finalize(self) }
+    unsafe fn finalize(self) -> Box<T> {
+        finalize(self)
+    }
 }
 
 impl<T> Boxed for Box<T> {
     type Data = T;
     type Place = IntermediateBox<T>;
-    unsafe fn finalize(b: IntermediateBox<T>) -> Box<T> { finalize(b) }
+    unsafe fn finalize(b: IntermediateBox<T>) -> Box<T> {
+        finalize(b)
+    }
 }
 
 impl<T> Placer<T> for ExchangeHeapSingleton {
@@ -191,9 +201,7 @@ impl<T> Placer<T> for ExchangeHeapSingleton {
 impl<T: ?Sized> Drop for IntermediateBox<T> {
     fn drop(&mut self) {
         if self.size > 0 {
-            unsafe {
-                heap::deallocate(self.ptr, self.size, self.align)
-            }
+            unsafe { heap::deallocate(self.ptr, self.size, self.align) }
         }
     }
 }
@@ -257,13 +265,17 @@ impl<T : ?Sized> Box<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Default> Default for Box<T> {
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn default() -> Box<T> { box Default::default() }
+    fn default() -> Box<T> {
+        box Default::default()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Default for Box<[T]> {
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn default() -> Box<[T]> { Box::<[T; 0]>::new([]) }
+    fn default() -> Box<[T]> {
+        Box::<[T; 0]>::new([])
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -276,8 +288,11 @@ impl<T: Clone> Clone for Box<T> {
     /// let x = Box::new(5);
     /// let y = x.clone();
     /// ```
+    #[rustfmt_skip]
     #[inline]
-    fn clone(&self) -> Box<T> { box {(**self).clone()} }
+    fn clone(&self) -> Box<T> {
+        box { (**self).clone() }
+    }
     /// Copies `source`'s contents into `self` without creating a new allocation.
     ///
     /// # Examples
@@ -312,9 +327,13 @@ impl Clone for Box<str> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + PartialEq> PartialEq for Box<T> {
     #[inline]
-    fn eq(&self, other: &Box<T>) -> bool { PartialEq::eq(&**self, &**other) }
+    fn eq(&self, other: &Box<T>) -> bool {
+        PartialEq::eq(&**self, &**other)
+    }
     #[inline]
-    fn ne(&self, other: &Box<T>) -> bool { PartialEq::ne(&**self, &**other) }
+    fn ne(&self, other: &Box<T>) -> bool {
+        PartialEq::ne(&**self, &**other)
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + PartialOrd> PartialOrd for Box<T> {
@@ -323,13 +342,21 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Box<T> {
         PartialOrd::partial_cmp(&**self, &**other)
     }
     #[inline]
-    fn lt(&self, other: &Box<T>) -> bool { PartialOrd::lt(&**self, &**other) }
+    fn lt(&self, other: &Box<T>) -> bool {
+        PartialOrd::lt(&**self, &**other)
+    }
     #[inline]
-    fn le(&self, other: &Box<T>) -> bool { PartialOrd::le(&**self, &**other) }
+    fn le(&self, other: &Box<T>) -> bool {
+        PartialOrd::le(&**self, &**other)
+    }
     #[inline]
-    fn ge(&self, other: &Box<T>) -> bool { PartialOrd::ge(&**self, &**other) }
+    fn ge(&self, other: &Box<T>) -> bool {
+        PartialOrd::ge(&**self, &**other)
+    }
     #[inline]
-    fn gt(&self, other: &Box<T>) -> bool { PartialOrd::gt(&**self, &**other) }
+    fn gt(&self, other: &Box<T>) -> bool {
+        PartialOrd::gt(&**self, &**other)
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + Ord> Ord for Box<T> {
@@ -357,8 +384,7 @@ impl Box<Any> {
             unsafe {
                 // Get the raw representation of the trait object
                 let raw = Box::into_raw(self);
-                let to: TraitObject =
-                    mem::transmute::<*mut Any, TraitObject>(raw);
+                let to: TraitObject = mem::transmute::<*mut Any, TraitObject>(raw);
 
                 // Extract the data pointer
                 Ok(Box::from_raw(to.data as *mut T))
@@ -409,23 +435,33 @@ impl<T> fmt::Pointer for Box<T> {
 impl<T: ?Sized> Deref for Box<T> {
     type Target = T;
 
-    fn deref(&self) -> &T { &**self }
+    fn deref(&self) -> &T {
+        &**self
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> DerefMut for Box<T> {
-    fn deref_mut(&mut self) -> &mut T { &mut **self }
+    fn deref_mut(&mut self) -> &mut T {
+        &mut **self
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<I: Iterator + ?Sized> Iterator for Box<I> {
     type Item = I::Item;
-    fn next(&mut self) -> Option<I::Item> { (**self).next() }
-    fn size_hint(&self) -> (usize, Option<usize>) { (**self).size_hint() }
+    fn next(&mut self) -> Option<I::Item> {
+        (**self).next()
+    }
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (**self).size_hint()
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> {
-    fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() }
+    fn next_back(&mut self) -> Option<I::Item> {
+        (**self).next_back()
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {}
@@ -509,7 +545,7 @@ impl<T: Clone> Clone for Box<[T]> {
     fn clone(&self) -> Self {
         let mut new = BoxBuilder {
             data: RawVec::with_capacity(self.len()),
-            len: 0
+            len: 0,
         };
 
         let mut target = new.data.ptr();
@@ -556,9 +592,27 @@ impl<T: Clone> Clone for Box<[T]> {
 }
 
 impl<T: ?Sized> borrow::Borrow<T> for Box<T> {
-    fn borrow(&self) -> &T { &**self }
+    fn borrow(&self) -> &T {
+        &**self
+    }
 }
 
 impl<T: ?Sized> borrow::BorrowMut<T> for Box<T> {
-    fn borrow_mut(&mut self) -> &mut T { &mut **self }
+    fn borrow_mut(&mut self) -> &mut T {
+        &mut **self
+    }
+}
+
+#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")]
+impl<T: ?Sized> AsRef<T> for Box<T> {
+    fn as_ref(&self) -> &T {
+        &**self
+    }
+}
+
+#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")]
+impl<T: ?Sized> AsMut<T> for Box<T> {
+    fn as_mut(&mut self) -> &mut T {
+        &mut **self
+    }
 }
index 2ef23b26a56a739549562c57ef71f521dab72063..7f3dadcf24d230998fb6a7084365e672a603824e 100644 (file)
@@ -34,12 +34,16 @@ fn any_move() {
     let b = Box::new(Test) as Box<Any>;
 
     match a.downcast::<i32>() {
-        Ok(a) => { assert!(a == Box::new(8)); }
-        Err(..) => panic!()
+        Ok(a) => {
+            assert!(a == Box::new(8));
+        }
+        Err(..) => panic!(),
     }
     match b.downcast::<Test>() {
-        Ok(a) => { assert!(a == Box::new(Test)); }
-        Err(..) => panic!()
+        Ok(a) => {
+            assert!(a == Box::new(Test));
+        }
+        Err(..) => panic!(),
     }
 
     let a = Box::new(8) as Box<Any>;
@@ -70,7 +74,8 @@ fn test_show() {
 
 #[test]
 fn deref() {
-    fn homura<T: Deref<Target=i32>>(_: T) { }
+    fn homura<T: Deref<Target = i32>>(_: T) {
+    }
     homura(Box::new(765));
 }
 
index 10cb84d1da14d1b8c94259efd30ff4228f26c2e8..6961702cbc09d4c66766646b8a1ef4e4f803b834 100644 (file)
@@ -22,18 +22,24 @@ extern {
     #[allocator]
     fn __rust_allocate(size: usize, align: usize) -> *mut u8;
     fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize);
-    fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize,
-                         align: usize) -> *mut u8;
-    fn __rust_reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize,
-                               align: usize) -> usize;
+    fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8;
+    fn __rust_reallocate_inplace(ptr: *mut u8,
+                                 old_size: usize,
+                                 size: usize,
+                                 align: usize)
+                                 -> usize;
     fn __rust_usable_size(size: usize, align: usize) -> usize;
 }
 
 #[inline(always)]
 fn check_size_and_alignment(size: usize, align: usize) {
     debug_assert!(size != 0);
-    debug_assert!(size <= isize::MAX as usize, "Tried to allocate too much: {} bytes", size);
-    debug_assert!(usize::is_power_of_two(align), "Invalid alignment of allocation: {}", align);
+    debug_assert!(size <= isize::MAX as usize,
+                  "Tried to allocate too much: {} bytes",
+                  size);
+    debug_assert!(usize::is_power_of_two(align),
+                  "Invalid alignment of allocation: {}",
+                  align);
 }
 
 // FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
@@ -84,8 +90,11 @@ pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usiz
 /// create the allocation referenced by `ptr`. The `old_size` parameter may be
 /// any value in range_inclusive(requested_size, usable_size).
 #[inline]
-pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize,
-                                 align: usize) -> usize {
+pub unsafe fn reallocate_inplace(ptr: *mut u8,
+                                 old_size: usize,
+                                 size: usize,
+                                 align: usize)
+                                 -> usize {
     check_size_and_alignment(size, align);
     __rust_reallocate_inplace(ptr, old_size, size, align)
 }
@@ -124,7 +133,9 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
         EMPTY as *mut u8
     } else {
         let ptr = allocate(size, align);
-        if ptr.is_null() { ::oom() }
+        if ptr.is_null() {
+            ::oom()
+        }
         ptr
     }
 }
@@ -148,7 +159,9 @@ mod tests {
         unsafe {
             let size = 4000;
             let ptr = heap::allocate(size, 8);
-            if ptr.is_null() { ::oom() }
+            if ptr.is_null() {
+                ::oom()
+            }
             let ret = heap::reallocate_inplace(ptr, size, size, 8);
             heap::deallocate(ptr, size, 8);
             assert_eq!(ret, heap::usable_size(size, 8));
index 1beb015364d9e4f80ed4091a7eaab02d0a5cecbe..c78ebdf4340ee28e845cc7e997f70e953d7a4c68 100644 (file)
 #![feature(placement_in_syntax)]
 #![feature(placement_new_protocol)]
 #![feature(raw)]
+#![feature(shared)]
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
 #![feature(unique)]
 #![feature(unsafe_no_drop_flag, filling_drop)]
+// SNAP 1af31d4
+#![allow(unused_features)]
+// SNAP 1af31d4
+#![allow(unused_attributes)]
+#![feature(dropck_parametricity)]
 #![feature(unsize)]
 #![feature(core_slice_ext)]
 #![feature(core_str_ext)]
 #![cfg_attr(stage0, feature(alloc_system))]
 #![cfg_attr(not(stage0), feature(needs_allocator))]
 
-#![cfg_attr(test, feature(test, rustc_private))]
+#![cfg_attr(test, feature(test, rustc_private, box_heap))]
 
 #[cfg(stage0)]
 extern crate alloc_system;
 
 // Allow testing this library
 
-#[cfg(test)] #[macro_use] extern crate std;
-#[cfg(test)] #[macro_use] extern crate log;
+#[cfg(test)]
+#[macro_use]
+extern crate std;
+#[cfg(test)]
+#[macro_use]
+extern crate log;
 
 // Heaps provided for low-level allocation strategies
 
@@ -123,7 +133,9 @@ pub mod heap;
 #[cfg(not(test))]
 pub mod boxed;
 #[cfg(test)]
-mod boxed { pub use std::boxed::{Box, HEAP}; }
+mod boxed {
+    pub use std::boxed::{Box, HEAP};
+}
 #[cfg(test)]
 mod boxed_test;
 pub mod arc;
index 97acd0db52478348da758770ee7e4a4b4ddf39d7..996a590043a47c04b997bab097dfc0ee9cf02130 100644 (file)
@@ -58,10 +58,17 @@ impl<T> RawVec<T> {
     pub fn new() -> Self {
         unsafe {
             // !0 is usize::MAX. This branch should be stripped at compile time.
-            let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
+            let cap = if mem::size_of::<T>() == 0 {
+                !0
+            } else {
+                0
+            };
 
             // heap::EMPTY doubles as "unallocated" and "zero-sized allocation"
-            RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: cap }
+            RawVec {
+                ptr: Unique::new(heap::EMPTY as *mut T),
+                cap: cap,
+            }
         }
     }
 
@@ -92,23 +99,31 @@ impl<T> RawVec<T> {
             } else {
                 let align = mem::align_of::<T>();
                 let ptr = heap::allocate(alloc_size, align);
-                if ptr.is_null() { oom() }
+                if ptr.is_null() {
+                    oom()
+                }
                 ptr
             };
 
-            RawVec { ptr: Unique::new(ptr as *mut _), cap: cap }
+            RawVec {
+                ptr: Unique::new(ptr as *mut _),
+                cap: cap,
+            }
         }
     }
 
     /// Reconstitutes a RawVec from a pointer and capacity.
     ///
-    /// # Undefined Behaviour
+    /// # Undefined Behavior
     ///
     /// The ptr must be allocated, and with the given capacity. The
     /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems).
     /// If the ptr and capacity come from a RawVec, then this is guaranteed.
     pub unsafe fn from_raw_parts(ptr: *mut T, cap: usize) -> Self {
-        RawVec { ptr: Unique::new(ptr), cap: cap }
+        RawVec {
+            ptr: Unique::new(ptr),
+            cap: cap,
+        }
     }
 
     /// Converts a `Box<[T]>` into a `RawVec<T>`.
@@ -133,7 +148,11 @@ impl<T> RawVec<T> {
     ///
     /// This will always be `usize::MAX` if `T` is zero-sized.
     pub fn cap(&self) -> usize {
-        if mem::size_of::<T>() == 0 { !0 } else { self.cap }
+        if mem::size_of::<T>() == 0 {
+            !0
+        } else {
+            self.cap
+        }
     }
 
     /// Doubles the size of the type's backing allocation. This is common enough
@@ -190,7 +209,11 @@ impl<T> RawVec<T> {
 
             let (new_cap, ptr) = if self.cap == 0 {
                 // skip to 4 because tiny Vec's are dumb; but not if that would cause overflow
-                let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
+                let new_cap = if elem_size > (!0) / 8 {
+                    1
+                } else {
+                    4
+                };
                 let ptr = heap::allocate(new_cap * elem_size, align);
                 (new_cap, ptr)
             } else {
@@ -207,7 +230,9 @@ impl<T> RawVec<T> {
             };
 
             // If allocate or reallocate fail, we'll get `null` back
-            if ptr.is_null() { oom() }
+            if ptr.is_null() {
+                oom()
+            }
 
             self.ptr = Unique::new(ptr as *mut _);
             self.cap = new_cap;
@@ -223,7 +248,7 @@ impl<T> RawVec<T> {
     ///
     /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate
     /// the requested space. This is not really unsafe, but the unsafe
-    /// code *you* write that relies on the behaviour of this function may break.
+    /// code *you* write that relies on the behavior of this function may break.
     ///
     /// # Panics
     ///
@@ -246,7 +271,9 @@ impl<T> RawVec<T> {
 
             // Don't actually need any more capacity.
             // Wrapping in case they gave a bad `used_cap`.
-            if self.cap().wrapping_sub(used_cap) >= needed_extra_cap { return; }
+            if self.cap().wrapping_sub(used_cap) >= needed_extra_cap {
+                return;
+            }
 
             // Nothing we can really do about these checks :(
             let new_cap = used_cap.checked_add(needed_extra_cap).expect("capacity overflow");
@@ -263,7 +290,9 @@ impl<T> RawVec<T> {
             };
 
             // If allocate or reallocate fail, we'll get `null` back
-            if ptr.is_null() { oom() }
+            if ptr.is_null() {
+                oom()
+            }
 
             self.ptr = Unique::new(ptr as *mut _);
             self.cap = new_cap;
@@ -273,12 +302,12 @@ impl<T> RawVec<T> {
     /// Ensures that the buffer contains at least enough space to hold
     /// `used_cap + needed_extra_cap` elements. If it doesn't already have
     /// enough capacity, will reallocate enough space plus comfortable slack
-    /// space to get amortized `O(1)` behaviour. Will limit this behaviour
+    /// space to get amortized `O(1)` behavior. Will limit this behavior
     /// if it would needlessly cause itself to panic.
     ///
     /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate
     /// the requested space. This is not really unsafe, but the unsafe
-    /// code *you* write that relies on the behaviour of this function may break.
+    /// code *you* write that relies on the behavior of this function may break.
     ///
     /// This is ideal for implementing a bulk-push operation like `extend`.
     ///
@@ -326,7 +355,9 @@ impl<T> RawVec<T> {
 
             // Don't actually need any more capacity.
             // Wrapping in case they give a bas `used_cap`
-            if self.cap().wrapping_sub(used_cap) >= needed_extra_cap { return; }
+            if self.cap().wrapping_sub(used_cap) >= needed_extra_cap {
+                return;
+            }
 
             // Nothing we can really do about these checks :(
             let new_cap = used_cap.checked_add(needed_extra_cap)
@@ -346,7 +377,9 @@ impl<T> RawVec<T> {
             };
 
             // If allocate or reallocate fail, we'll get `null` back
-            if ptr.is_null() { oom() }
+            if ptr.is_null() {
+                oom()
+            }
 
             self.ptr = Unique::new(ptr as *mut _);
             self.cap = new_cap;
@@ -386,7 +419,9 @@ impl<T> RawVec<T> {
                                            self.cap * elem_size,
                                            amount * elem_size,
                                            align);
-                if ptr.is_null() { oom() }
+                if ptr.is_null() {
+                    oom()
+                }
                 self.ptr = Unique::new(ptr as *mut _);
             }
             self.cap = amount;
@@ -395,7 +430,7 @@ impl<T> RawVec<T> {
 
     /// Converts the entire buffer into `Box<[T]>`.
     ///
-    /// While it is not *strictly* Undefined Behaviour to call
+    /// While it is not *strictly* Undefined Behavior to call
     /// this procedure while some of the RawVec is unintialized,
     /// it cetainly makes it trivial to trigger it.
     ///
@@ -418,6 +453,7 @@ impl<T> RawVec<T> {
 }
 
 impl<T> Drop for RawVec<T> {
+    #[unsafe_destructor_blind_to_params]
     /// Frees the memory owned by the RawVec *without* trying to Drop its contents.
     fn drop(&mut self) {
         let elem_size = mem::size_of::<T>();
@@ -446,6 +482,7 @@ impl<T> Drop for RawVec<T> {
 #[inline]
 fn alloc_guard(alloc_size: usize) {
     if core::usize::BITS < 64 {
-        assert!(alloc_size <= ::core::isize::MAX as usize, "capacity overflow");
+        assert!(alloc_size <= ::core::isize::MAX as usize,
+                "capacity overflow");
     }
 }
index 4fe474cef0a26e21a69fc69ebb126bed2e16d7f4..d695c0edd1dc82f0b625ec6f7f75aebaff214404 100644 (file)
@@ -163,9 +163,8 @@ use core::hash::{Hasher, Hash};
 use core::intrinsics::{assume, drop_in_place, abort};
 use core::marker::{self, Unsize};
 use core::mem::{self, align_of_val, size_of_val, forget};
-use core::nonzero::NonZero;
 use core::ops::{CoerceUnsized, Deref};
-use core::ptr;
+use core::ptr::{self, Shared};
 
 use heap::deallocate;
 
@@ -184,12 +183,13 @@ struct RcBox<T: ?Sized> {
 pub struct Rc<T: ?Sized> {
     // FIXME #12808: strange names to try to avoid interfering with field
     // accesses of the contained type via Deref
-    _ptr: NonZero<*mut RcBox<T>>,
+    _ptr: Shared<RcBox<T>>,
 }
 
 impl<T: ?Sized> !marker::Send for Rc<T> {}
 impl<T: ?Sized> !marker::Sync for Rc<T> {}
 
+#[cfg(not(stage0))] // remove cfg after new snapshot
 impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Rc<U>> for Rc<T> {}
 
 impl<T> Rc<T> {
@@ -210,10 +210,10 @@ impl<T> Rc<T> {
                 // pointers, which ensures that the weak destructor never frees
                 // the allocation while the strong destructor is running, even
                 // if the weak pointer is stored inside the strong one.
-                _ptr: NonZero::new(Box::into_raw(box RcBox {
+                _ptr: Shared::new(Box::into_raw(box RcBox {
                     strong: Cell::new(1),
                     weak: Cell::new(1),
-                    value: value
+                    value: value,
                 })),
             }
         }
@@ -290,13 +290,17 @@ impl<T: ?Sized> Rc<T> {
     #[inline]
     #[unstable(feature = "rc_counts", reason = "not clearly useful",
                issue = "28356")]
-    pub fn weak_count(this: &Self) -> usize { this.weak() - 1 }
+    pub fn weak_count(this: &Self) -> usize {
+        this.weak() - 1
+    }
 
     /// Get the number of strong references to this value.
     #[inline]
     #[unstable(feature = "rc_counts", reason = "not clearly useful",
                issue = "28356")]
-    pub fn strong_count(this: &Self) -> usize { this.strong() }
+    pub fn strong_count(this: &Self) -> usize {
+        this.strong()
+    }
 
     /// Returns true if there are no other `Rc` or `Weak<T>` values that share
     /// the same inner value.
@@ -447,11 +451,12 @@ impl<T: ?Sized> Drop for Rc<T> {
     ///
     /// } // implicit drop
     /// ```
+    #[unsafe_destructor_blind_to_params]
     fn drop(&mut self) {
         unsafe {
             let ptr = *self._ptr;
             if !(*(&ptr as *const _ as *const *const ())).is_null() &&
-                ptr as *const () as usize != mem::POST_DROP_USIZE {
+               ptr as *const () as usize != mem::POST_DROP_USIZE {
                 self.dec_strong();
                 if self.strong() == 0 {
                     // destroy the contained object
@@ -462,9 +467,7 @@ impl<T: ?Sized> Drop for Rc<T> {
                     self.dec_weak();
 
                     if self.weak() == 0 {
-                        deallocate(ptr as *mut u8,
-                                   size_of_val(&*ptr),
-                                   align_of_val(&*ptr))
+                        deallocate(ptr as *mut u8, size_of_val(&*ptr), align_of_val(&*ptr))
                     }
                 }
             }
@@ -530,7 +533,9 @@ impl<T: ?Sized + PartialEq> PartialEq for Rc<T> {
     /// five == Rc::new(5);
     /// ```
     #[inline(always)]
-    fn eq(&self, other: &Rc<T>) -> bool { **self == **other }
+    fn eq(&self, other: &Rc<T>) -> bool {
+        **self == **other
+    }
 
     /// Inequality for two `Rc<T>`s.
     ///
@@ -546,7 +551,9 @@ impl<T: ?Sized + PartialEq> PartialEq for Rc<T> {
     /// five != Rc::new(5);
     /// ```
     #[inline(always)]
-    fn ne(&self, other: &Rc<T>) -> bool { **self != **other }
+    fn ne(&self, other: &Rc<T>) -> bool {
+        **self != **other
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -586,7 +593,9 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Rc<T> {
     /// five < Rc::new(5);
     /// ```
     #[inline(always)]
-    fn lt(&self, other: &Rc<T>) -> bool { **self < **other }
+    fn lt(&self, other: &Rc<T>) -> bool {
+        **self < **other
+    }
 
     /// 'Less-than or equal to' comparison for two `Rc<T>`s.
     ///
@@ -602,7 +611,9 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Rc<T> {
     /// five <= Rc::new(5);
     /// ```
     #[inline(always)]
-    fn le(&self, other: &Rc<T>) -> bool { **self <= **other }
+    fn le(&self, other: &Rc<T>) -> bool {
+        **self <= **other
+    }
 
     /// Greater-than comparison for two `Rc<T>`s.
     ///
@@ -618,7 +629,9 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Rc<T> {
     /// five > Rc::new(5);
     /// ```
     #[inline(always)]
-    fn gt(&self, other: &Rc<T>) -> bool { **self > **other }
+    fn gt(&self, other: &Rc<T>) -> bool {
+        **self > **other
+    }
 
     /// 'Greater-than or equal to' comparison for two `Rc<T>`s.
     ///
@@ -634,7 +647,9 @@ impl<T: ?Sized + PartialOrd> PartialOrd for Rc<T> {
     /// five >= Rc::new(5);
     /// ```
     #[inline(always)]
-    fn ge(&self, other: &Rc<T>) -> bool { **self >= **other }
+    fn ge(&self, other: &Rc<T>) -> bool {
+        **self >= **other
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -653,7 +668,9 @@ impl<T: ?Sized + Ord> Ord for Rc<T> {
     /// five.partial_cmp(&Rc::new(5));
     /// ```
     #[inline]
-    fn cmp(&self, other: &Rc<T>) -> Ordering { (**self).cmp(&**other) }
+    fn cmp(&self, other: &Rc<T>) -> Ordering {
+        (**self).cmp(&**other)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -695,12 +712,13 @@ impl<T> fmt::Pointer for Rc<T> {
 pub struct Weak<T: ?Sized> {
     // FIXME #12808: strange names to try to avoid interfering with
     // field accesses of the contained type via Deref
-    _ptr: NonZero<*mut RcBox<T>>,
+    _ptr: Shared<RcBox<T>>,
 }
 
 impl<T: ?Sized> !marker::Send for Weak<T> {}
 impl<T: ?Sized> !marker::Sync for Weak<T> {}
 
+#[cfg(not(stage0))] // remove cfg after new snapshot
 impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
 
 impl<T: ?Sized> Weak<T> {
@@ -764,13 +782,12 @@ impl<T: ?Sized> Drop for Weak<T> {
         unsafe {
             let ptr = *self._ptr;
             if !(*(&ptr as *const _ as *const *const ())).is_null() &&
-                ptr as *const () as usize != mem::POST_DROP_USIZE {
+               ptr as *const () as usize != mem::POST_DROP_USIZE {
                 self.dec_weak();
                 // the weak count starts at 1, and will only go to zero if all
                 // the strong pointers have disappeared.
                 if self.weak() == 0 {
-                    deallocate(ptr as *mut u8, size_of_val(&*ptr),
-                               align_of_val(&*ptr))
+                    deallocate(ptr as *mut u8, size_of_val(&*ptr), align_of_val(&*ptr))
                 }
             }
         }
@@ -821,7 +838,9 @@ trait RcBoxPtr<T: ?Sized> {
     fn inner(&self) -> &RcBox<T>;
 
     #[inline]
-    fn strong(&self) -> usize { self.inner().strong.get() }
+    fn strong(&self) -> usize {
+        self.inner().strong.get()
+    }
 
     #[inline]
     fn inc_strong(&self) {
@@ -829,10 +848,14 @@ trait RcBoxPtr<T: ?Sized> {
     }
 
     #[inline]
-    fn dec_strong(&self) { self.inner().strong.set(self.strong() - 1); }
+    fn dec_strong(&self) {
+        self.inner().strong.set(self.strong() - 1);
+    }
 
     #[inline]
-    fn weak(&self) -> usize { self.inner().weak.get() }
+    fn weak(&self) -> usize {
+        self.inner().weak.get()
+    }
 
     #[inline]
     fn inc_weak(&self) {
@@ -840,7 +863,9 @@ trait RcBoxPtr<T: ?Sized> {
     }
 
     #[inline]
-    fn dec_weak(&self) { self.inner().weak.set(self.weak() - 1); }
+    fn dec_weak(&self) {
+        self.inner().weak.set(self.weak() - 1);
+    }
 }
 
 impl<T: ?Sized> RcBoxPtr<T> for Rc<T> {
@@ -928,7 +953,7 @@ mod tests {
     #[test]
     fn weak_self_cyclic() {
         struct Cycle {
-            x: RefCell<Option<Weak<Cycle>>>
+            x: RefCell<Option<Weak<Cycle>>>,
         }
 
         let a = Rc::new(Cycle { x: RefCell::new(None) });
@@ -1086,5 +1111,14 @@ mod tests {
 }
 
 impl<T: ?Sized> borrow::Borrow<T> for Rc<T> {
-    fn borrow(&self) -> &T { &**self }
+    fn borrow(&self) -> &T {
+        &**self
+    }
+}
+
+#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")]
+impl<T: ?Sized> AsRef<T> for Rc<T> {
+    fn as_ref(&self) -> &T {
+        &**self
+    }
 }
index 4179cbe8a7bac6b905848e0cc0bd1a7a10cc8a9e..f46b12e80c56ada9cae738e5b6934bd2e4b4b85f 100644 (file)
@@ -27,23 +27,27 @@ extern crate libc;
 
 use libc::{c_int, c_void, size_t};
 
+// Linkage directives to pull in jemalloc and its dependencies.
+//
+// On some platforms we need to be sure to link in `pthread` which jemalloc
+// depends on, and specifically on android we need to also link to libgcc.
+// Currently jemalloc is compiled with gcc which will generate calls to
+// intrinsics that are libgcc specific (e.g. those intrinsics aren't present in
+// libcompiler-rt), so link that in to get that support.
 #[link(name = "jemalloc", kind = "static")]
+#[cfg_attr(target_os = "android", link(name = "gcc"))]
+#[cfg_attr(all(not(windows),
+               not(target_os = "android"),
+               not(target_env = "musl")),
+           link(name = "pthread"))]
 extern {
     fn je_mallocx(size: size_t, flags: c_int) -> *mut c_void;
     fn je_rallocx(ptr: *mut c_void, size: size_t, flags: c_int) -> *mut c_void;
-    fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t,
-                  flags: c_int) -> size_t;
+    fn je_xallocx(ptr: *mut c_void, size: size_t, extra: size_t, flags: c_int) -> size_t;
     fn je_sdallocx(ptr: *mut c_void, size: size_t, flags: c_int);
     fn je_nallocx(size: size_t, flags: c_int) -> size_t;
 }
 
-// -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
-#[cfg(all(not(windows),
-          not(target_os = "android"),
-          not(target_env = "musl")))]
-#[link(name = "pthread")]
-extern {}
-
 // The minimum alignment guaranteed by the architecture. This value is used to
 // add fast paths for low alignment values. In practice, the alignment is a
 // constant at the call site and the branch will be optimized out.
@@ -58,40 +62,52 @@ const MIN_ALIGN: usize = 8;
 const MIN_ALIGN: usize = 16;
 
 // MALLOCX_ALIGN(a) macro
-fn mallocx_align(a: usize) -> c_int { a.trailing_zeros() as c_int }
+fn mallocx_align(a: usize) -> c_int {
+    a.trailing_zeros() as c_int
+}
 
 fn align_to_flags(align: usize) -> c_int {
-    if align <= MIN_ALIGN { 0 } else { mallocx_align(align) }
+    if align <= MIN_ALIGN {
+        0
+    } else {
+        mallocx_align(align)
+    }
 }
 
 #[no_mangle]
-pub extern fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
+pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
     let flags = align_to_flags(align);
     unsafe { je_mallocx(size as size_t, flags) as *mut u8 }
 }
 
 #[no_mangle]
-pub extern fn __rust_reallocate(ptr: *mut u8, _old_size: usize, size: usize,
-                                align: usize) -> *mut u8 {
+pub extern "C" fn __rust_reallocate(ptr: *mut u8,
+                                    _old_size: usize,
+                                    size: usize,
+                                    align: usize)
+                                    -> *mut u8 {
     let flags = align_to_flags(align);
     unsafe { je_rallocx(ptr as *mut c_void, size as size_t, flags) as *mut u8 }
 }
 
 #[no_mangle]
-pub extern fn __rust_reallocate_inplace(ptr: *mut u8, _old_size: usize,
-                                        size: usize, align: usize) -> usize {
+pub extern "C" fn __rust_reallocate_inplace(ptr: *mut u8,
+                                            _old_size: usize,
+                                            size: usize,
+                                            align: usize)
+                                            -> usize {
     let flags = align_to_flags(align);
     unsafe { je_xallocx(ptr as *mut c_void, size as size_t, 0, flags) as usize }
 }
 
 #[no_mangle]
-pub extern fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) {
+pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) {
     let flags = align_to_flags(align);
     unsafe { je_sdallocx(ptr as *mut c_void, old_size as size_t, flags) }
 }
 
 #[no_mangle]
-pub extern fn __rust_usable_size(size: usize, align: usize) -> usize {
+pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize {
     let flags = align_to_flags(align);
     unsafe { je_nallocx(size as size_t, flags) as usize }
 }
index aff4bea19e0f306636d3622df74bc1962bcc1648..c447dfbec4440b75995adc50880e75b75ac65d50 100644 (file)
@@ -39,29 +39,35 @@ const MIN_ALIGN: usize = 8;
 const MIN_ALIGN: usize = 16;
 
 #[no_mangle]
-pub extern fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
+pub extern "C" fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
     unsafe { imp::allocate(size, align) }
 }
 
 #[no_mangle]
-pub extern fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) {
+pub extern "C" fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) {
     unsafe { imp::deallocate(ptr, old_size, align) }
 }
 
 #[no_mangle]
-pub extern fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize,
-                                align: usize) -> *mut u8 {
+pub extern "C" fn __rust_reallocate(ptr: *mut u8,
+                                    old_size: usize,
+                                    size: usize,
+                                    align: usize)
+                                    -> *mut u8 {
     unsafe { imp::reallocate(ptr, old_size, size, align) }
 }
 
 #[no_mangle]
-pub extern fn __rust_reallocate_inplace(ptr: *mut u8, old_size: usize,
-                                        size: usize, align: usize) -> usize {
+pub extern "C" fn __rust_reallocate_inplace(ptr: *mut u8,
+                                            old_size: usize,
+                                            size: usize,
+                                            align: usize)
+                                            -> usize {
     unsafe { imp::reallocate_inplace(ptr, old_size, size, align) }
 }
 
 #[no_mangle]
-pub extern fn __rust_usable_size(size: usize, align: usize) -> usize {
+pub extern "C" fn __rust_usable_size(size: usize, align: usize) -> usize {
     imp::usable_size(size, align)
 }
 
@@ -80,7 +86,8 @@ mod imp {
         #[cfg(not(target_os = "android"))]
         fn posix_memalign(memptr: *mut *mut libc::c_void,
                           align: libc::size_t,
-                          size: libc::size_t) -> libc::c_int;
+                          size: libc::size_t)
+                          -> libc::c_int;
     }
 
     pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
@@ -94,9 +101,7 @@ mod imp {
             #[cfg(not(target_os = "android"))]
             unsafe fn more_aligned_malloc(size: usize, align: usize) -> *mut u8 {
                 let mut out = ptr::null_mut();
-                let ret = posix_memalign(&mut out,
-                                         align as libc::size_t,
-                                         size as libc::size_t);
+                let ret = posix_memalign(&mut out, align as libc::size_t, size as libc::size_t);
                 if ret != 0 {
                     ptr::null_mut()
                 } else {
@@ -107,8 +112,7 @@ mod imp {
         }
     }
 
-    pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize,
-                             align: usize) -> *mut u8 {
+    pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
         if align <= MIN_ALIGN {
             libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
         } else {
@@ -119,8 +123,11 @@ mod imp {
         }
     }
 
-    pub unsafe fn reallocate_inplace(_ptr: *mut u8, old_size: usize, _size: usize,
-                                     _align: usize) -> usize {
+    pub unsafe fn reallocate_inplace(_ptr: *mut u8,
+                                     old_size: usize,
+                                     _size: usize,
+                                     _align: usize)
+                                     -> usize {
         old_size
     }
 
@@ -141,8 +148,7 @@ mod imp {
     extern "system" {
         fn GetProcessHeap() -> HANDLE;
         fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
-        fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID,
-                       dwBytes: SIZE_T) -> LPVOID;
+        fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
         fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
     }
 
@@ -165,32 +171,45 @@ mod imp {
         if align <= MIN_ALIGN {
             HeapAlloc(GetProcessHeap(), 0, size as SIZE_T) as *mut u8
         } else {
-            let ptr = HeapAlloc(GetProcessHeap(), 0,
-                                (size + align) as SIZE_T) as *mut u8;
-            if ptr.is_null() { return ptr }
+            let ptr = HeapAlloc(GetProcessHeap(), 0, (size + align) as SIZE_T) as *mut u8;
+            if ptr.is_null() {
+                return ptr
+            }
             align_ptr(ptr, align)
         }
     }
 
-    pub unsafe fn reallocate(ptr: *mut u8, _old_size: usize, size: usize,
-                             align: usize) -> *mut u8 {
+    pub unsafe fn reallocate(ptr: *mut u8, _old_size: usize, size: usize, align: usize) -> *mut u8 {
         if align <= MIN_ALIGN {
             HeapReAlloc(GetProcessHeap(), 0, ptr as LPVOID, size as SIZE_T) as *mut u8
         } else {
             let header = get_header(ptr);
-            let new = HeapReAlloc(GetProcessHeap(), 0, header.0 as LPVOID,
+            let new = HeapReAlloc(GetProcessHeap(),
+                                  0,
+                                  header.0 as LPVOID,
                                   (size + align) as SIZE_T) as *mut u8;
-            if new.is_null() { return new }
+            if new.is_null() {
+                return new
+            }
             align_ptr(new, align)
         }
     }
 
-    pub unsafe fn reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize,
-                                     align: usize) -> usize {
+    pub unsafe fn reallocate_inplace(ptr: *mut u8,
+                                     old_size: usize,
+                                     size: usize,
+                                     align: usize)
+                                     -> usize {
         if align <= MIN_ALIGN {
-            let new = HeapReAlloc(GetProcessHeap(), HEAP_REALLOC_IN_PLACE_ONLY,
-                                  ptr as LPVOID, size as SIZE_T) as *mut u8;
-            if new.is_null() { old_size } else { size }
+            let new = HeapReAlloc(GetProcessHeap(),
+                                  HEAP_REALLOC_IN_PLACE_ONLY,
+                                  ptr as LPVOID,
+                                  size as SIZE_T) as *mut u8;
+            if new.is_null() {
+                old_size
+            } else {
+                size
+            }
         } else {
             old_size
         }
index 57e82720e8beaf3fc0a4a9c645a2b79d1a9c47c5..5bc1c44e1b1fb11281cb64f1ec38a710e57da10c 100644 (file)
 #![feature(ptr_as_ref)]
 #![feature(raw)]
 #![feature(staged_api)]
+#![feature(dropck_parametricity)]
 #![cfg_attr(test, feature(test))]
 
+// SNAP 1af31d4
+#![allow(unused_features)]
+// SNAP 1af31d4
+#![allow(unused_attributes)]
+
 extern crate alloc;
 
 use std::cell::{Cell, RefCell};
@@ -99,7 +105,7 @@ pub struct Arena<'longer_than_self> {
     head: RefCell<Chunk>,
     copy_head: RefCell<Chunk>,
     chunks: RefCell<Vec<Chunk>>,
-    _marker: marker::PhantomData<*mut &'longer_than_self()>,
+    _marker: marker::PhantomData<*mut &'longer_than_self ()>,
 }
 
 impl<'a> Arena<'a> {
@@ -191,7 +197,7 @@ fn un_bitpack_tydesc_ptr(p: usize) -> (*const TyDesc, bool) {
 struct TyDesc {
     drop_glue: fn(*const i8),
     size: usize,
-    align: usize
+    align: usize,
 }
 
 trait AllTypes { fn dummy(&self) { } }
@@ -218,8 +224,7 @@ impl<'longer_than_self> Arena<'longer_than_self> {
         let new_min_chunk_size = cmp::max(n_bytes, self.chunk_size());
         self.chunks.borrow_mut().push(self.copy_head.borrow().clone());
 
-        *self.copy_head.borrow_mut() =
-            chunk((new_min_chunk_size + 1).next_power_of_two(), true);
+        *self.copy_head.borrow_mut() = chunk((new_min_chunk_size + 1).next_power_of_two(), true);
 
         self.alloc_copy_inner(n_bytes, align)
     }
@@ -236,16 +241,15 @@ impl<'longer_than_self> Arena<'longer_than_self> {
         let copy_head = self.copy_head.borrow();
         copy_head.fill.set(end);
 
-        unsafe {
-            copy_head.as_ptr().offset(start as isize)
-        }
+        unsafe { copy_head.as_ptr().offset(start as isize) }
     }
 
     #[inline]
-    fn alloc_copy<T, F>(&self, op: F) -> &mut T where F: FnOnce() -> T {
+    fn alloc_copy<T, F>(&self, op: F) -> &mut T
+        where F: FnOnce() -> T
+    {
         unsafe {
-            let ptr = self.alloc_copy_inner(mem::size_of::<T>(),
-                                            mem::align_of::<T>());
+            let ptr = self.alloc_copy_inner(mem::size_of::<T>(), mem::align_of::<T>());
             let ptr = ptr as *mut T;
             ptr::write(&mut (*ptr), op());
             &mut *ptr
@@ -253,21 +257,18 @@ impl<'longer_than_self> Arena<'longer_than_self> {
     }
 
     // Functions for the non-POD part of the arena
-    fn alloc_noncopy_grow(&self, n_bytes: usize,
-                          align: usize) -> (*const u8, *const u8) {
+    fn alloc_noncopy_grow(&self, n_bytes: usize, align: usize) -> (*const u8, *const u8) {
         // Allocate a new chunk.
         let new_min_chunk_size = cmp::max(n_bytes, self.chunk_size());
         self.chunks.borrow_mut().push(self.head.borrow().clone());
 
-        *self.head.borrow_mut() =
-            chunk((new_min_chunk_size + 1).next_power_of_two(), false);
+        *self.head.borrow_mut() = chunk((new_min_chunk_size + 1).next_power_of_two(), false);
 
         self.alloc_noncopy_inner(n_bytes, align)
     }
 
     #[inline]
-    fn alloc_noncopy_inner(&self, n_bytes: usize,
-                           align: usize) -> (*const u8, *const u8) {
+    fn alloc_noncopy_inner(&self, n_bytes: usize, align: usize) -> (*const u8, *const u8) {
         // Be careful to not maintain any `head` borrows active, because
         // `alloc_noncopy_grow` borrows it mutably.
         let (start, end, tydesc_start, head_capacity) = {
@@ -291,24 +292,25 @@ impl<'longer_than_self> Arena<'longer_than_self> {
 
         unsafe {
             let buf = head.as_ptr();
-            (buf.offset(tydesc_start as isize), buf.offset(start as isize))
+            (buf.offset(tydesc_start as isize),
+             buf.offset(start as isize))
         }
     }
 
     #[inline]
-    fn alloc_noncopy<T, F>(&self, op: F) -> &mut T where F: FnOnce() -> T {
+    fn alloc_noncopy<T, F>(&self, op: F) -> &mut T
+        where F: FnOnce() -> T
+    {
         unsafe {
             let tydesc = get_tydesc::<T>();
-            let (ty_ptr, ptr) =
-                self.alloc_noncopy_inner(mem::size_of::<T>(),
-                                         mem::align_of::<T>());
+            let (ty_ptr, ptr) = self.alloc_noncopy_inner(mem::size_of::<T>(), mem::align_of::<T>());
             let ty_ptr = ty_ptr as *mut usize;
             let ptr = ptr as *mut T;
             // Write in our tydesc along with a bit indicating that it
             // has *not* been initialized yet.
             *ty_ptr = bitpack_tydesc_ptr(tydesc, false);
             // Actually initialize it
-            ptr::write(&mut(*ptr), op());
+            ptr::write(&mut (*ptr), op());
             // Now that we are done, update the tydesc to indicate that
             // the object is there.
             *ty_ptr = bitpack_tydesc_ptr(tydesc, true);
@@ -320,7 +322,9 @@ impl<'longer_than_self> Arena<'longer_than_self> {
     /// Allocates a new item in the arena, using `op` to initialize the value,
     /// and returns a reference to it.
     #[inline]
-    pub fn alloc<T:'longer_than_self, F>(&self, op: F) -> &mut T where F: FnOnce() -> T {
+    pub fn alloc<T: 'longer_than_self, F>(&self, op: F) -> &mut T
+        where F: FnOnce() -> T
+    {
         unsafe {
             if intrinsics::needs_drop::<T>() {
                 self.alloc_noncopy(op)
@@ -352,10 +356,10 @@ fn test_arena_destructors_fail() {
     for i in 0..10 {
         // Arena allocate something with drop glue to make sure it
         // doesn't leak.
-        arena.alloc(|| { Rc::new(i) });
+        arena.alloc(|| Rc::new(i));
         // Allocate something with funny size and alignment, to keep
         // things interesting.
-        arena.alloc(|| { [0u8, 1, 2] });
+        arena.alloc(|| [0u8, 1, 2]);
     }
     // Now, panic while allocating
     arena.alloc::<Rc<i32>, _>(|| {
@@ -403,12 +407,13 @@ fn calculate_size<T>(capacity: usize) -> usize {
 
 impl<T> TypedArenaChunk<T> {
     #[inline]
-    unsafe fn new(next: *mut TypedArenaChunk<T>, capacity: usize)
-           -> *mut TypedArenaChunk<T> {
+    unsafe fn new(next: *mut TypedArenaChunk<T>, capacity: usize) -> *mut TypedArenaChunk<T> {
         let size = calculate_size::<T>(capacity);
-        let chunk = allocate(size, mem::align_of::<TypedArenaChunk<T>>())
-                    as *mut TypedArenaChunk<T>;
-        if chunk.is_null() { alloc::oom() }
+        let chunk =
+            allocate(size, mem::align_of::<TypedArenaChunk<T>>()) as *mut TypedArenaChunk<T>;
+        if chunk.is_null() {
+            alloc::oom()
+        }
         (*chunk).next = next;
         (*chunk).capacity = capacity;
         chunk
@@ -431,7 +436,8 @@ impl<T> TypedArenaChunk<T> {
         let next = self.next;
         let size = calculate_size::<T>(self.capacity);
         let self_ptr: *mut TypedArenaChunk<T> = self;
-        deallocate(self_ptr as *mut u8, size,
+        deallocate(self_ptr as *mut u8,
+                   size,
                    mem::align_of::<TypedArenaChunk<T>>());
         if !next.is_null() {
             let capacity = (*next).capacity;
@@ -443,9 +449,7 @@ impl<T> TypedArenaChunk<T> {
     #[inline]
     fn start(&self) -> *const u8 {
         let this: *const TypedArenaChunk<T> = self;
-        unsafe {
-            round_up(this.offset(1) as usize, mem::align_of::<T>()) as *const u8
-        }
+        unsafe { round_up(this.offset(1) as usize, mem::align_of::<T>()) as *const u8 }
     }
 
     // Returns a pointer to the end of the allocated space.
@@ -510,6 +514,7 @@ impl<T> TypedArena<T> {
 }
 
 impl<T> Drop for TypedArena<T> {
+    #[unsafe_destructor_blind_to_params]
     fn drop(&mut self) {
         unsafe {
             // Determine how much was filled.
@@ -538,14 +543,21 @@ mod tests {
 
     #[test]
     fn test_arena_alloc_nested() {
-        struct Inner { value: u8 }
-        struct Outer<'a> { inner: &'a Inner }
-        enum EI<'e> { I(Inner), O(Outer<'e>) }
+        struct Inner {
+            value: u8,
+        }
+        struct Outer<'a> {
+            inner: &'a Inner,
+        }
+        enum EI<'e> {
+            I(Inner),
+            O(Outer<'e>),
+        }
 
         struct Wrap<'a>(TypedArena<EI<'a>>);
 
         impl<'a> Wrap<'a> {
-            fn alloc_inner<F:Fn() -> Inner>(&self, f: F) -> &Inner {
+            fn alloc_inner<F: Fn() -> Inner>(&self, f: F) -> &Inner {
                 let r: &EI = self.0.alloc(EI::I(f()));
                 if let &EI::I(ref i) = r {
                     i
@@ -553,7 +565,7 @@ mod tests {
                     panic!("mismatch");
                 }
             }
-            fn alloc_outer<F:Fn() -> Outer<'a>>(&self, f: F) -> &Outer {
+            fn alloc_outer<F: Fn() -> Outer<'a>>(&self, f: F) -> &Outer {
                 let r: &EI = self.0.alloc(EI::O(f()));
                 if let &EI::O(ref o) = r {
                     o
@@ -565,8 +577,9 @@ mod tests {
 
         let arena = Wrap(TypedArena::new());
 
-        let result = arena.alloc_outer(|| Outer {
-            inner: arena.alloc_inner(|| Inner { value: 10 }) });
+        let result = arena.alloc_outer(|| {
+            Outer { inner: arena.alloc_inner(|| Inner { value: 10 }) }
+        });
 
         assert_eq!(result.inner.value, 10);
     }
@@ -575,49 +588,27 @@ mod tests {
     pub fn test_copy() {
         let arena = TypedArena::new();
         for _ in 0..100000 {
-            arena.alloc(Point {
-                x: 1,
-                y: 2,
-                z: 3,
-            });
+            arena.alloc(Point { x: 1, y: 2, z: 3 });
         }
     }
 
     #[bench]
     pub fn bench_copy(b: &mut Bencher) {
         let arena = TypedArena::new();
-        b.iter(|| {
-            arena.alloc(Point {
-                x: 1,
-                y: 2,
-                z: 3,
-            })
-        })
+        b.iter(|| arena.alloc(Point { x: 1, y: 2, z: 3 }))
     }
 
     #[bench]
     pub fn bench_copy_nonarena(b: &mut Bencher) {
         b.iter(|| {
-            let _: Box<_> = box Point {
-                x: 1,
-                y: 2,
-                z: 3,
-            };
+            let _: Box<_> = box Point { x: 1, y: 2, z: 3 };
         })
     }
 
     #[bench]
     pub fn bench_copy_old_arena(b: &mut Bencher) {
         let arena = Arena::new();
-        b.iter(|| {
-            arena.alloc(|| {
-                Point {
-                    x: 1,
-                    y: 2,
-                    z: 3,
-                }
-            })
-        })
+        b.iter(|| arena.alloc(|| Point { x: 1, y: 2, z: 3 }))
     }
 
     #[allow(dead_code)]
@@ -632,7 +623,7 @@ mod tests {
         for _ in 0..100000 {
             arena.alloc(Noncopy {
                 string: "hello world".to_string(),
-                array: vec!( 1, 2, 3, 4, 5 ),
+                array: vec!(1, 2, 3, 4, 5),
             });
         }
     }
@@ -643,7 +634,7 @@ mod tests {
         b.iter(|| {
             arena.alloc(Noncopy {
                 string: "hello world".to_string(),
-                array: vec!( 1, 2, 3, 4, 5 ),
+                array: vec!(1, 2, 3, 4, 5),
             })
         })
     }
@@ -653,7 +644,7 @@ mod tests {
         b.iter(|| {
             let _: Box<_> = box Noncopy {
                 string: "hello world".to_string(),
-                array: vec!( 1, 2, 3, 4, 5 ),
+                array: vec!(1, 2, 3, 4, 5),
             };
         })
     }
@@ -662,9 +653,11 @@ mod tests {
     pub fn bench_noncopy_old_arena(b: &mut Bencher) {
         let arena = Arena::new();
         b.iter(|| {
-            arena.alloc(|| Noncopy {
-                string: "hello world".to_string(),
-                array: vec!( 1, 2, 3, 4, 5 ),
+            arena.alloc(|| {
+                Noncopy {
+                    string: "hello world".to_string(),
+                    array: vec!(1, 2, 3, 4, 5),
+                }
             })
         })
     }
index 6b60e3b3b07382a48c7ffbaf992876426234bdee..5ab329c696d77d808f8359baa0074376da9c7f0f 100644 (file)
@@ -6,7 +6,7 @@
 
        * configure.ac: Add --enable-host-shared.
        * configure: Regenerate.
-\f
+
 Copyright (C) 2013-2014 Free Software Foundation, Inc.
 
 Copying and distribution of this file, with or without modification,
index c5f0dcbcf7a19157326dec3e9e408d4cdafd8e60..ea78c701632166d9832d89d1448f58fbc24954fa 100644 (file)
@@ -6,12 +6,12 @@
 # met:
 
 #     (1) Redistributions of source code must retain the above copyright
-#     notice, this list of conditions and the following disclaimer. 
+#     notice, this list of conditions and the following disclaimer.
 
 #     (2) Redistributions in binary form must reproduce the above copyright
 #     notice, this list of conditions and the following disclaimer in
 #     the documentation and/or other materials provided with the
-#     distribution.  
+#     distribution.
 
 #     (3) The name of the author may not be used to
 #     endorse or promote products derived from this software without
index b434d76edb620e81aa048bdea1019c0fd8213a4a..16b1a72712ffd044dcb36849aa678abe8a7242aa 100644 (file)
 # met:
 
 #     (1) Redistributions of source code must retain the above copyright
-#     notice, this list of conditions and the following disclaimer. 
+#     notice, this list of conditions and the following disclaimer.
 
 #     (2) Redistributions in binary form must reproduce the above copyright
 #     notice, this list of conditions and the following disclaimer in
 #     the documentation and/or other materials provided with the
-#     distribution.  
+#     distribution.
 
 #     (3) The name of the author may not be used to
 #     endorse or promote products derived from this software without
@@ -137,10 +137,10 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
        $(LDFLAGS) -o $@
 SOURCES = $(libbacktrace_la_SOURCES) $(EXTRA_libbacktrace_la_SOURCES) \
        $(btest_SOURCES) $(stest_SOURCES)
-MULTISRCTOP = 
-MULTIBUILDTOP = 
-MULTIDIRS = 
-MULTISUBDIR = 
+MULTISRCTOP =
+MULTIBUILDTOP =
+MULTIDIRS =
+MULTISUBDIR =
 MULTIDO = true
 MULTICLEAN = true
 am__can_run_installinfo = \
@@ -389,7 +389,7 @@ config.h: stamp-h1
 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
        @rm -f stamp-h1
        cd $(top_builddir) && $(SHELL) ./config.status config.h
-$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) 
+$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
        ($(am__cd) $(top_srcdir) && $(AUTOHEADER))
        rm -f stamp-h1
        touch $@
@@ -407,7 +407,7 @@ clean-noinstLTLIBRARIES:
          echo "rm -f \"$${dir}/so_locations\""; \
          rm -f "$${dir}/so_locations"; \
        done
-libbacktrace.la: $(libbacktrace_la_OBJECTS) $(libbacktrace_la_DEPENDENCIES) $(EXTRA_libbacktrace_la_DEPENDENCIES) 
+libbacktrace.la: $(libbacktrace_la_OBJECTS) $(libbacktrace_la_DEPENDENCIES) $(EXTRA_libbacktrace_la_DEPENDENCIES)
        $(LINK)  $(libbacktrace_la_OBJECTS) $(libbacktrace_la_LIBADD) $(LIBS)
 
 clean-checkPROGRAMS:
@@ -418,10 +418,10 @@ clean-checkPROGRAMS:
        list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
        echo " rm -f" $$list; \
        rm -f $$list
-btest$(EXEEXT): $(btest_OBJECTS) $(btest_DEPENDENCIES) $(EXTRA_btest_DEPENDENCIES) 
+btest$(EXEEXT): $(btest_OBJECTS) $(btest_DEPENDENCIES) $(EXTRA_btest_DEPENDENCIES)
        @rm -f btest$(EXEEXT)
        $(btest_LINK) $(btest_OBJECTS) $(btest_LDADD) $(LIBS)
-stest$(EXEEXT): $(stest_OBJECTS) $(stest_DEPENDENCIES) $(EXTRA_stest_DEPENDENCIES) 
+stest$(EXEEXT): $(stest_OBJECTS) $(stest_DEPENDENCIES) $(EXTRA_stest_DEPENDENCIES)
        @rm -f stest$(EXEEXT)
        $(LINK) $(stest_OBJECTS) $(stest_LDADD) $(LIBS)
 
index 143ef68ca5148943104b14eb40cc1f3fa8808f7a..c9d6a1406b7b2e58110593e5ef64fe18e1511204 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index fdd2490da7c6bdcd50e9e328e5ba495b11557e47..40e4ff93cf68ace004289f81ff5e347d8e8f96a0 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index ab051a1689826ba57d4bdf8688beb1a643a97e98..976963e71041ba8dce060e56ce4f5949f7303801 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index d352d27a4006d98a755a1a16cbeeb53a4c2d3cf2..8941375c6cd5575ceecd08b65a1202218eb28568 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index 50dcd40751b22c7268ef001e8a397cf274d79b7a..f16ee36cbce9ad9ab00da24d0e146d017392efd1 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index 9821e34c0c1ba69c48b98e71b75e46533c8a030e..a950a704f071d7caf2e3fd9fa5f04b9ae8d38e0c 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
@@ -460,7 +460,7 @@ f23 (int f1line, int f2line)
                       (unsigned int) bdata.index, j + 1);
              bdata.failed = 1;
            }
-       }      
+       }
 
       check ("test3", 0, all, f3line, "f23", &bdata.failed);
       check ("test3", 1, all, f2line, "f22", &bdata.failed);
index a0e487bb42d71fa88cda59a0b16cbf733716cfaa..30d890ef14a9fb44c75e189941877f08366f1658 100644 (file)
@@ -6,13 +6,13 @@
 # met:
 
 #     (1) Redistributions of source code must retain the above copyright
-#     notice, this list of conditions and the following disclaimer. 
+#     notice, this list of conditions and the following disclaimer.
 
 #     (2) Redistributions in binary form must reproduce the above copyright
 #     notice, this list of conditions and the following disclaimer in
 #     the documentation and/or other materials provided with the
-#     distribution.  
-    
+#     distribution.
+
 #     (3) The name of the author may not be used to
 #     endorse or promote products derived from this software without
 #     specific prior written permission.
index 54e5ace9b4a68cc557fcc96dce7477ea01af4a62..fd3beac01fbafd8f8f9e60f82a3e436f6e4ba917 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
@@ -1246,7 +1246,7 @@ add_unit_ranges (struct backtrace_state *state, uintptr_t base_address,
 
 static int
 find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
-                    struct dwarf_buf *unit_buf, 
+                    struct dwarf_buf *unit_buf,
                     const unsigned char *dwarf_str, size_t dwarf_str_size,
                     const unsigned char *dwarf_ranges,
                     size_t dwarf_ranges_size,
@@ -1605,7 +1605,7 @@ read_line_header (struct backtrace_state *state, struct unit *u,
 
   if (!advance (line_buf, hdrlen))
     return 0;
-  
+
   hdr->min_insn_len = read_byte (&hdr_buf);
   if (hdr->version < 4)
     hdr->max_ops_per_insn = 1;
@@ -1614,7 +1614,7 @@ read_line_header (struct backtrace_state *state, struct unit *u,
 
   /* We don't care about default_is_stmt.  */
   read_byte (&hdr_buf);
-  
+
   hdr->line_base = read_sbyte (&hdr_buf);
   hdr->line_range = read_byte (&hdr_buf);
 
index 71a37b30c9f87b429bab08a4a420caa9a6385503..932ce86435131a1f54aafad359afd6168e45cd50 100644 (file)
 
 /* This file declares various DWARF-related constants using a set of
    macros which can be redefined by the including file.
-   
+
    The macros are in sections.  Each section corresponds to a single
    set of DWARF constants and has a corresponding key.  The key is
    used in all the macro names.
-   
+
    The sections are TAG (for DW_TAG_ constants), FORM (DW_FORM_), AT
    (DW_AT_), OP (DW_OP_), ATE (DW_ATE_), and CFA (DW_CFA_).
-   
+
    Using TAG as an example, the following macros may be used for each
    key:
-   
+
    DW_FIRST_TAG(name, value) - Introduce the first DW_TAG constant.
-   
+
    DW_TAG(name, value) - Define a subsequent constant.
-   
+
    DW_TAG_DUP(name, value) - Define a subsequent constant whose value
    is a duplicate of some other constant.  Not all keys use the _DUP
    macro form.  If more than one name shares a value, then the base
    (DW_TAG) form will be the preferred name and DW_TAG_DUP will hold
    any alternate names.
-   
+
    DW_END_TAG - Invoked at the end of the DW_TAG constants.  */
 
 DW_FIRST_TAG (DW_TAG_padding, 0x00)
index 120e2c16b4820f823c75ab8b2aa7c00bab6291fa..c7d49ebb2401b6fb79ce4158e055760fb7d15744 100644 (file)
@@ -352,7 +352,7 @@ enum dwarf_macro_record_type
     DW_MACRO_GNU_lo_user = 0xe0,
     DW_MACRO_GNU_hi_user = 0xff
   };
-\f
+
 /* @@@ For use with GNU frame unwind information.  */
 
 #define DW_EH_PE_absptr                0x00
index 3f14b11a43c8388f9220122ce8b3e47e1137e0b5..f0709c9c355dc4f028d95ffb703c0f894727ce41 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index 0acad0603eeb071a4b114cf3a7f544536a1be405..c151147213431f29cedda13f78655835dd93e9ac 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index 30f99ca127f8e8035b18c4b772adf989aa508fbf..f6046ee6057c5c621fe0fedd22c7a289e2522903 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index 1ecf131191142879ca808b864eb47810a71c5bbe..610548a8a4e220d9b008b7d23a17ff9a0c9c603f 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index b5a787e0aa6fd8bd8a50a37167b1d0ef3c9922bc..45f81a8593d9f72197a0001cb8e93e0b920d3fb2 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index f53f906b5a89cb2c617067ed3b43b99acd0cec01..9952c0bcbfb7bd5b8c452837bd1690612d301d20 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index 7fa7cd0d5da6760713ca827d90858105a4d4ab12..f6260a0044eaa0855d6202bd329fa40cf0107569 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index 90ecaf89edad0258b80aed7232cba4fe87352500..271f41c0c59bfeebcb6c9d72d2ac659ca0afcacd 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index 299f77ba7c629848f8e22b113f15f2c96747c0ea..70dd91ee97c8fd805e59be4c087a4b9b2669817b 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index 39c2e902ff77b17adf036f388fd6bc8b25f36aa4..fc0f4f498012c883b3dea172e5b94423605a8724 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index bcc765e93aa777e736ed0b685015398c5fb67dc5..01b1cb2b8a5553cf397ab3c01ca64088172210d8 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index a846378e903c2c7876b9a875cde369c5ffa0332e..373938865c7fff4236ca6fd6a85fd2e5302e478b 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index ec93e680e89ed8cda9571e03ff92939190d89e5f..510715291895ca8065ee95e3180df4d06388210d 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index e89cba96f7d91565d1ab307c238cc6b23dbed283..953e96e510e593f33369d1f5bf28d68bd347722c 100644 (file)
@@ -7,13 +7,13 @@ modification, are permitted provided that the following conditions are
 met:
 
     (1) Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer. 
+    notice, this list of conditions and the following disclaimer.
 
     (2) Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in
     the documentation and/or other materials provided with the
-    distribution.  
-    
+    distribution.
+
     (3) The name of the author may not be used to
     endorse or promote products derived from this software without
     specific prior written permission.
index a3e32b59b710de007c03d43b47f70e9f5b13bff6..30fc22e400a81a65273278b7d8e41e875739eda3 100644 (file)
@@ -167,12 +167,22 @@ use vec::{self, Vec};
 /// item's ordering relative to any other item, as determined by the `Ord`
 /// trait, changes while it is in the heap. This is normally only possible
 /// through `Cell`, `RefCell`, global state, I/O, or unsafe code.
-#[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct BinaryHeap<T> {
     data: Vec<T>,
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: Clone> Clone for BinaryHeap<T> {
+    fn clone(&self) -> Self {
+        BinaryHeap { data: self.data.clone() }
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        self.data.clone_from(&source.data);
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> Default for BinaryHeap<T> {
     #[inline]
@@ -230,14 +240,9 @@ impl<T: Ord> BinaryHeap<T> {
     #[unstable(feature = "binary_heap_extras",
                reason = "needs to be audited",
                issue = "28147")]
+    #[deprecated(since = "1.5.0", reason = "use BinaryHeap::from instead")]
     pub fn from_vec(vec: Vec<T>) -> BinaryHeap<T> {
-        let mut heap = BinaryHeap { data: vec };
-        let mut n = heap.len() / 2;
-        while n > 0 {
-            n -= 1;
-            heap.sift_down(n);
-        }
-        heap
+        BinaryHeap::from(vec)
     }
 
     /// Returns an iterator visiting all values in the underlying vector, in
@@ -246,10 +251,8 @@ impl<T: Ord> BinaryHeap<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(binary_heap_extras)]
-    ///
     /// use std::collections::BinaryHeap;
-    /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]);
+    /// let heap = BinaryHeap::from(vec![1, 2, 3, 4]);
     ///
     /// // Print 1, 2, 3, 4 in arbitrary order
     /// for x in heap.iter() {
@@ -352,10 +355,8 @@ impl<T: Ord> BinaryHeap<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(binary_heap_extras)]
-    ///
     /// use std::collections::BinaryHeap;
-    /// let mut heap = BinaryHeap::from_vec(vec![1, 3]);
+    /// let mut heap = BinaryHeap::from(vec![1, 3]);
     ///
     /// assert_eq!(heap.pop(), Some(3));
     /// assert_eq!(heap.pop(), Some(1));
@@ -465,10 +466,8 @@ impl<T: Ord> BinaryHeap<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(binary_heap_extras)]
-    ///
     /// use std::collections::BinaryHeap;
-    /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4, 5, 6, 7]);
+    /// let heap = BinaryHeap::from(vec![1, 2, 3, 4, 5, 6, 7]);
     /// let vec = heap.into_vec();
     ///
     /// // Will print in some order
@@ -476,10 +475,10 @@ impl<T: Ord> BinaryHeap<T> {
     ///     println!("{}", x);
     /// }
     /// ```
-    #[unstable(feature = "binary_heap_extras",
-               reason = "needs to be audited",
-               issue = "28147")]
-    pub fn into_vec(self) -> Vec<T> { self.data }
+    #[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
+    pub fn into_vec(self) -> Vec<T> {
+        self.into()
+    }
 
     /// Consumes the `BinaryHeap` and returns a vector in sorted
     /// (ascending) order.
@@ -487,20 +486,16 @@ impl<T: Ord> BinaryHeap<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(binary_heap_extras)]
-    ///
     /// use std::collections::BinaryHeap;
     ///
-    /// let mut heap = BinaryHeap::from_vec(vec![1, 2, 4, 5, 7]);
+    /// let mut heap = BinaryHeap::from(vec![1, 2, 4, 5, 7]);
     /// heap.push(6);
     /// heap.push(3);
     ///
     /// let vec = heap.into_sorted_vec();
     /// assert_eq!(vec, [1, 2, 3, 4, 5, 6, 7]);
     /// ```
-    #[unstable(feature = "binary_heap_extras",
-               reason = "needs to be audited",
-               issue = "28147")]
+    #[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
     pub fn into_sorted_vec(mut self) -> Vec<T> {
         let mut end = self.len();
         while end > 1 {
@@ -734,10 +729,28 @@ impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {}
 
+impl<T: Ord> From<Vec<T>> for BinaryHeap<T> {
+    fn from(vec: Vec<T>) -> BinaryHeap<T> {
+        let mut heap = BinaryHeap { data: vec };
+        let mut n = heap.len() / 2;
+        while n > 0 {
+            n -= 1;
+            heap.sift_down(n);
+        }
+        heap
+    }
+}
+
+impl<T> From<BinaryHeap<T>> for Vec<T> {
+    fn from(heap: BinaryHeap<T>) -> Vec<T> {
+        heap.data
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> FromIterator<T> for BinaryHeap<T> {
     fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> BinaryHeap<T> {
-        BinaryHeap::from_vec(iter.into_iter().collect())
+        BinaryHeap::from(iter.into_iter().collect::<Vec<_>>())
     }
 }
 
@@ -753,10 +766,8 @@ impl<T: Ord> IntoIterator for BinaryHeap<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(binary_heap_extras)]
-    ///
     /// use std::collections::BinaryHeap;
-    /// let heap = BinaryHeap::from_vec(vec![1, 2, 3, 4]);
+    /// let heap = BinaryHeap::from(vec![1, 2, 3, 4]);
     ///
     /// // Print 1, 2, 3, 4 in arbitrary order
     /// for x in heap.into_iter() {
index aedfbe546de65e38f6545a503ea188f640d91aef..1ad836f9bdfb965ffbf31dc57d3414bbf0c1d16f 100644 (file)
@@ -315,8 +315,14 @@ impl<K: Ord, V> BTreeMap<K, V> {
     // 2) While ODS may potentially return the pair we *just* inserted after
     // the split, we will never do this. Again, this shouldn't effect the analysis.
 
-    /// Inserts a key-value pair into the map. If the key already had a value
-    /// present in the map, that value is returned. Otherwise, `None` is returned.
+    /// Inserts a key-value pair into the map.
+    ///
+    /// If the map did not have this key present, `None` is returned.
+    ///
+    /// If the map did have this key present, that value is returned, and the
+    /// entry is not updated. See the [module-level documentation] for more.
+    ///
+    /// [module-level documentation]: index.html#insert-and-complex-keys
     ///
     /// # Examples
     ///
@@ -593,7 +599,7 @@ mod stack {
         top: node::Handle<*mut Node<K, V>, Type, NodeType>,
     }
 
-    /// A `PartialSearchStack` that doesn't hold a reference to the next node, and is just
+    /// A `PartialSearchStack` that doesn't hold a reference to the next node, and is just
     /// just waiting for a `Handle` to that next node to be pushed. See `PartialSearchStack::with`
     /// for more details.
     pub struct Pusher<'id, 'a, K:'a, V:'a> {
@@ -949,7 +955,7 @@ impl<'a, K: Ord, Q: ?Sized, V> Index<&'a Q> for BTreeMap<K, V>
     }
 }
 
-/// Genericises over how to get the correct type of iterator from the correct type
+/// Genericizes over how to get the correct type of iterator from the correct type
 /// of Node ownership.
 trait Traverse<N> {
     fn traverse(node: N) -> Self;
index d8f8ca6eae59c84e3daef5e4db8eae1ee4297ccf..4380f315ee7f12de54ae460c131e0c43f8c43e6c 100644 (file)
@@ -164,7 +164,12 @@ fn calculate_allocation_generic<K, V>(capacity: usize, is_leaf: bool) -> (usize,
     let (keys_size, keys_align) = (capacity * mem::size_of::<K>(), mem::align_of::<K>());
     let (vals_size, vals_align) = (capacity * mem::size_of::<V>(), mem::align_of::<V>());
     let (edges_size, edges_align) = if is_leaf {
-        (0, 1)
+        // allocate one edge to ensure that we don't pass size 0 to `heap::allocate`
+        if mem::size_of::<K>() == 0 && mem::size_of::<V>() == 0 {
+            (1, mem::align_of::<Node<K, V>>())
+        } else {
+            (0, 1)
+        }
     } else {
         ((capacity + 1) * mem::size_of::<Node<K, V>>(), mem::align_of::<Node<K, V>>())
     };
@@ -270,12 +275,14 @@ impl<T> DoubleEndedIterator for RawItems<T> {
 }
 
 impl<T> Drop for RawItems<T> {
+    #[unsafe_destructor_blind_to_params]
     fn drop(&mut self) {
-        for _ in self.by_ref() {}
+        for _ in self {}
     }
 }
 
 impl<K, V> Drop for Node<K, V> {
+    #[unsafe_destructor_blind_to_params]
     fn drop(&mut self) {
         if self.keys.is_null() ||
             (unsafe { self.keys.get() as *const K as usize == mem::POST_DROP_USIZE })
@@ -811,7 +818,7 @@ impl<K, V, NodeRef> Handle<NodeRef, handle::Edge, handle::Internal> where
         }
     }
 
-    /// Handle an underflow in this node's child. We favour handling "to the left" because we know
+    /// Handle an underflow in this node's child. We favor handling "to the left" because we know
     /// we're empty, but our neighbour can be full. Handling to the left means when we choose to
     /// steal, we pop off the end of our neighbour (always fast) and "unshift" ourselves
     /// (always slow, but at least faster since we know we're half-empty).
@@ -1414,6 +1421,7 @@ impl<K, V> TraversalImpl for MoveTraversalImpl<K, V> {
 }
 
 impl<K, V> Drop for MoveTraversalImpl<K, V> {
+    #[unsafe_destructor_blind_to_params]
     fn drop(&mut self) {
         // We need to cleanup the stored values manually, as the RawItems destructor would run
         // after our deallocation.
index eb2a6d5e088948bce606212b7b6443c5dffa94dc..3ca0aa377c102fd4c397a4bc9d9016974660f75f 100644 (file)
@@ -430,8 +430,14 @@ impl<T: Ord> BTreeSet<T> {
         other.is_subset(self)
     }
 
-    /// Adds a value to the set. Returns `true` if the value was not already
-    /// present in the set.
+    /// Adds a value to the set.
+    ///
+    /// If the set did not have a value present, `true` is returned.
+    ///
+    /// If the set did have this key present, that value is returned, and the
+    /// entry is not updated. See the [module-level documentation] for more.
+    ///
+    /// [module-level documentation]: index.html#insert-and-complex-keys
     ///
     /// # Examples
     ///
index 7e7e8ba2356e36b6396328f19c0769a3f7d41286..32cd4193d8855983b2a645479e890d721c540525 100644 (file)
@@ -49,16 +49,7 @@ impl<E> Clone for EnumSet<E> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<E:CLike + fmt::Debug> fmt::Debug for EnumSet<E> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(fmt, "{{"));
-        let mut first = true;
-        for e in self {
-            if !first {
-                try!(write!(fmt, ", "));
-            }
-            try!(write!(fmt, "{:?}", e));
-            first = false;
-        }
-        write!(fmt, "}}")
+        fmt.debug_set().entries(self).finish()
     }
 }
 
index d17bd5cccf50ed00e1b90b8b70d12f16c3ffaa13..a31ad6c1093628c1b42b21d13a8cdfdce57bbc81 100644 (file)
 //! }
 //! ```
 //!
-//! ### fmt::Display vs fmt::Debug
+//! ### `fmt::Display` vs `fmt::Debug`
 //!
 //! These two formatting traits have distinct purposes:
 //!
 //! to ensure padding is applied is to format your input, then use this
 //! resulting string to pad your output.
 //!
-//! ## Sign/#/0
+//! ## Sign/`#`/`0`
 //!
 //! These can all be interpreted as flags for a particular formatter.
 //!
-//! * '+' - This is intended for numeric types and indicates that the sign
+//! * `+` - This is intended for numeric types and indicates that the sign
 //!         should always be printed. Positive signs are never printed by
 //!         default, and the negative sign is only printed by default for the
-//!         `Signed` trait. This flag indicates that the correct sign (+ or -)
+//!         `Signed` trait. This flag indicates that the correct sign (`+` or `-`)
 //!         should always be printed.
-//! * '-' - Currently not used
-//! * '#' - This flag is indicates that the "alternate" form of printing should
+//! * `-` - Currently not used
+//! * `#` - This flag is indicates that the "alternate" form of printing should
 //!         be used. The alternate forms are:
 //!     * `#?` - pretty-print the `Debug` formatting
-//!     * `#x` - precedes the argument with a "0x"
-//!     * `#X` - precedes the argument with a "0x"
-//!     * `#b` - precedes the argument with a "0b"
-//!     * `#o` - precedes the argument with a "0o"
-//! * '0' - This is used to indicate for integer formats that the padding should
+//!     * `#x` - precedes the argument with a `0x`
+//!     * `#X` - precedes the argument with a `0x`
+//!     * `#b` - precedes the argument with a `0b`
+//!     * `#o` - precedes the argument with a `0o`
+//! * `0` - This is used to indicate for integer formats that the padding should
 //!         both be done with a `0` character as well as be sign-aware. A format
 //!         like `{:08}` would yield `00000001` for the integer `1`, while the
 //!         same format would yield `-0000001` for the integer `-1`. Notice that
 //!
 //! The default fill/alignment for non-numerics is a space and left-aligned. The
 //! defaults for numeric formatters is also a space but with right-alignment. If
-//! the '0' flag is specified for numerics, then the implicit fill character is
-//! '0'.
+//! the `0` flag is specified for numerics, then the implicit fill character is
+//! `0`.
 //!
 //! The value for the width can also be provided as a `usize` in the list of
 //! parameters by using the `2$` syntax indicating that the second argument is a
index fe06e3fb2093ed456b9be851087fc9c48f0afe94..3bb8a11c6a57d4f9664d958a57f921ba7db5481e 100644 (file)
 #![allow(trivial_casts)]
 #![cfg_attr(test, allow(deprecated))] // rand
 
+// SNAP 1af31d4
+#![allow(unused_features)]
+// SNAP 1af31d4
+#![allow(unused_attributes)]
+
 #![feature(alloc)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(core_intrinsics)]
 #![feature(core_slice_ext)]
 #![feature(core_str_ext)]
+#![feature(fmt_internals)]
+#![feature(fmt_radix)]
 #![feature(heap_api)]
-#![feature(iter_order)]
 #![feature(iter_arith)]
 #![feature(iter_arith)]
 #![feature(lang_items)]
 #![feature(oom)]
 #![feature(pattern)]
 #![feature(ptr_as_ref)]
+#![feature(ref_slice)]
+#![feature(slice_bytes)]
 #![feature(slice_patterns)]
 #![feature(staged_api)]
 #![feature(step_by)]
 #![feature(str_char)]
-#![feature(str_match_indices)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
 #![feature(unique)]
+#![feature(dropck_parametricity)]
 #![feature(unsafe_no_drop_flag, filling_drop)]
 #![feature(decode_utf16)]
-#![feature(utf8_error)]
-#![cfg_attr(test, feature(rand, test))]
+#![cfg_attr(test, feature(clone_from_slice, rand, test))]
 
 #![feature(no_std)]
 #![no_std]
index 891e8b7b2c961c35aebb7083047d722cf3d86c5e..fca7d3b26fc2e538d98fadaeae14a276dca3d8d7 100644 (file)
@@ -655,6 +655,7 @@ impl<T> LinkedList<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for LinkedList<T> {
+    #[unsafe_destructor_blind_to_params]
     fn drop(&mut self) {
         // Dissolve the linked_list in a loop.
         // Just dropping the list_head can lead to stack exhaustion
index 76bdd6dbea1221a69da5864a649ebb97f8233b20..ea4830fc3e6cefab41c11700a2e8e924a9637007 100644 (file)
@@ -106,6 +106,7 @@ pub use core::slice::{Chunks, Windows};
 pub use core::slice::{Iter, IterMut};
 pub use core::slice::{SplitMut, ChunksMut, Split};
 pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
+#[allow(deprecated)]
 pub use core::slice::{bytes, mut_ref_slice, ref_slice};
 pub use core::slice::{from_raw_parts, from_raw_parts_mut};
 
@@ -214,21 +215,21 @@ impl<T> [T] {
     }
 
     /// Returns the first and all the rest of the elements of a slice.
-    #[unstable(feature = "slice_splits", reason = "new API", issue = "27742")]
+    #[stable(feature = "slice_splits", since = "1.5.0")]
     #[inline]
     pub fn split_first(&self) -> Option<(&T, &[T])> {
         core_slice::SliceExt::split_first(self)
     }
 
     /// Returns the first and all the rest of the elements of a slice.
-    #[unstable(feature = "slice_splits", reason = "new API", issue = "27742")]
+    #[stable(feature = "slice_splits", since = "1.5.0")]
     #[inline]
     pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
         core_slice::SliceExt::split_first_mut(self)
     }
 
     /// Returns the last and all the rest of the elements of a slice.
-    #[unstable(feature = "slice_splits", reason = "new API", issue = "27742")]
+    #[stable(feature = "slice_splits", since = "1.5.0")]
     #[inline]
     pub fn split_last(&self) -> Option<(&T, &[T])> {
         core_slice::SliceExt::split_last(self)
@@ -236,7 +237,7 @@ impl<T> [T] {
     }
 
     /// Returns the last and all the rest of the elements of a slice.
-    #[unstable(feature = "slice_splits", reason = "new API", issue = "27742")]
+    #[stable(feature = "slice_splits", since = "1.5.0")]
     #[inline]
     pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
         core_slice::SliceExt::split_last_mut(self)
@@ -455,6 +456,8 @@ impl<T> [T] {
     /// the index `mid` itself) and the second will contain all
     /// indices from `[mid, len)` (excluding the index `len` itself).
     ///
+    /// # Panics
+    ///
     /// Panics if `mid > len`.
     ///
     /// # Examples
index fbb6c279bbcd8c951efbdd23ee63a18601951f0f..21406354d81c3ea4241a102dc3764aca7d68eca7 100644 (file)
@@ -38,6 +38,7 @@ use slice::SliceConcatExt;
 use boxed::Box;
 
 pub use core::str::{FromStr, Utf8Error};
+#[allow(deprecated)]
 pub use core::str::{Lines, LinesAny, CharRange};
 pub use core::str::{Split, RSplit};
 pub use core::str::{SplitN, RSplitN};
@@ -101,7 +102,7 @@ impl<S: Borrow<str>> SliceConcatExt<str> for [S] {
     }
 }
 
-/// External iterator for a string's UTF16 codeunits.
+/// External iterator for a string's UTF-16 code units.
 ///
 /// For use with the `std::iter` module.
 #[derive(Clone)]
@@ -253,7 +254,7 @@ impl str {
     ///
     /// Returns the substring from [`begin`..`end`).
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// Caller must check both UTF-8 sequence boundaries and the boundaries
     /// of the entire slice as well.
@@ -276,8 +277,7 @@ impl str {
     /// Takes a bytewise mutable slice from a string.
     ///
     /// Same as `slice_unchecked`, but works with `&mut str` instead of `&str`.
-    #[unstable(feature = "str_slice_mut", reason = "recently added",
-               issue = "27793")]
+    #[stable(feature = "str_slice_mut", since = "1.5.0")]
     #[inline]
     pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str {
         core_str::StrExt::slice_mut_unchecked(self, begin, end)
@@ -505,8 +505,6 @@ impl str {
     ///
     /// # Examples
     /// ```
-    /// #![feature(str_split_at)]
-    ///
     /// let s = "Löwe 老虎 Léopard";
     /// let first_space = s.find(' ').unwrap_or(s.len());
     /// let (a, b) = s.split_at(first_space);
@@ -714,8 +712,7 @@ impl str {
     /// Returns `None` if it doesn't exist.
     ///
     /// The pattern can be a simple `&str`, `char`, or a closure that
-    /// determines the
-    /// split.
+    /// determines if a character matches.
     ///
     /// # Examples
     ///
@@ -759,7 +756,7 @@ impl str {
     /// Returns `None` if it doesn't exist.
     ///
     /// The pattern can be a simple `&str`, `char`,
-    /// or a closure that determines the split.
+    /// or a closure that determines if a character matches.
     ///
     /// # Examples
     ///
@@ -869,6 +866,10 @@ impl str {
     /// ```rust,ignore
     /// assert_eq!(d, &["a", "b", "c"]);
     /// ```
+    ///
+    /// Use [`.split_whitespace()`][split_whitespace] for this behavior.
+    ///
+    /// [split_whitespace]: #method.split_whitespace
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
         core_str::StrExt::split(self, pat)
@@ -1095,7 +1096,7 @@ impl str {
     /// An iterator over the matches of a pattern within `self`.
     ///
     /// The pattern can be a simple `&str`, `char`, or a closure that
-    /// determines the split.
+    /// determines if a character matches.
     /// Additional libraries might provide more complex patterns like
     /// regular expressions.
     ///
@@ -1128,7 +1129,7 @@ impl str {
     /// reverse order.
     ///
     /// The pattern can be a simple `&str`, `char`, or a closure that
-    /// determines the split.
+    /// determines if a character matches.
     /// Additional libraries might provide more complex patterns like
     /// regular expressions.
     ///
@@ -1157,26 +1158,21 @@ impl str {
         core_str::StrExt::rmatches(self, pat)
     }
 
-    /// An iterator over the start and end indices of the disjoint matches
-    /// of a pattern within `self`.
+    /// An iterator over the disjoint matches of a pattern within `self` as well
+    /// as the index that the match starts at.
     ///
     /// For matches of `pat` within `self` that overlap, only the indices
-    /// corresponding to the first
-    /// match are returned.
+    /// corresponding to the first match are returned.
     ///
-    /// The pattern can be a simple `&str`, `char`, or a closure that
-    /// determines
-    /// the split.
-    /// Additional libraries might provide more complex patterns like
-    /// regular expressions.
+    /// The pattern can be a simple `&str`, `char`, or a closure that determines
+    /// if a character matches. Additional libraries might provide more complex
+    /// patterns like regular expressions.
     ///
     /// # Iterator behavior
     ///
     /// The returned iterator will be double ended if the pattern allows a
-    /// reverse search
-    /// and forward/reverse search yields the same elements. This is true for,
-    /// eg, `char` but not
-    /// for `&str`.
+    /// reverse search and forward/reverse search yields the same elements. This
+    /// is true for, eg, `char` but not for `&str`.
     ///
     /// If the pattern allows a reverse search but its results might differ
     /// from a forward search, `rmatch_indices()` can be used.
@@ -1186,43 +1182,34 @@ impl str {
     /// ```
     /// #![feature(str_match_indices)]
     ///
-    /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".match_indices("abc").collect();
-    /// assert_eq!(v, [(0, 3), (6, 9), (12, 15)]);
+    /// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect();
+    /// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]);
     ///
-    /// let v: Vec<(usize, usize)> = "1abcabc2".match_indices("abc").collect();
-    /// assert_eq!(v, [(1, 4), (4, 7)]);
+    /// let v: Vec<_> = "1abcabc2".match_indices("abc").collect();
+    /// assert_eq!(v, [(1, "abc"), (4, "abc")]);
     ///
-    /// let v: Vec<(usize, usize)> = "ababa".match_indices("aba").collect();
-    /// assert_eq!(v, [(0, 3)]); // only the first `aba`
+    /// let v: Vec<_> = "ababa".match_indices("aba").collect();
+    /// assert_eq!(v, [(0, "aba")]); // only the first `aba`
     /// ```
-    #[unstable(feature = "str_match_indices",
-               reason = "might have its iterator type changed",
-               issue = "27743")]
-    // NB: Right now MatchIndices yields `(usize, usize)`, but it would
-    // be more consistent with `matches` and `char_indices` to return `(usize, &str)`
+    #[stable(feature = "str_match_indices", since = "1.5.0")]
     pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
         core_str::StrExt::match_indices(self, pat)
     }
 
-    /// An iterator over the start and end indices of the disjoint matches of
-    /// a pattern within
-    /// `self`, yielded in reverse order.
+    /// An iterator over the disjoint matches of a pattern within `self`,
+    /// yielded in reverse order along with the index of the match.
     ///
     /// For matches of `pat` within `self` that overlap, only the indices
-    /// corresponding to the last
-    /// match are returned.
+    /// corresponding to the last match are returned.
     ///
-    /// The pattern can be a simple `&str`, `char`, or a closure that
-    /// determines
-    /// the split.
-    /// Additional libraries might provide more complex patterns like
-    /// regular expressions.
+    /// The pattern can be a simple `&str`, `char`, or a closure that determines
+    /// if a character matches. Additional libraries might provide more complex
+    /// patterns like regular expressions.
     ///
     /// # Iterator behavior
     ///
-    /// The returned iterator requires that the pattern supports a
-    /// reverse search,
-    /// and it will be double ended if a forward/reverse search yields
+    /// The returned iterator requires that the pattern supports a reverse
+    /// search, and it will be double ended if a forward/reverse search yields
     /// the same elements.
     ///
     /// For iterating from the front, `match_indices()` can be used.
@@ -1232,20 +1219,16 @@ impl str {
     /// ```
     /// #![feature(str_match_indices)]
     ///
-    /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".rmatch_indices("abc").collect();
-    /// assert_eq!(v, [(12, 15), (6, 9), (0, 3)]);
+    /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect();
+    /// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]);
     ///
-    /// let v: Vec<(usize, usize)> = "1abcabc2".rmatch_indices("abc").collect();
-    /// assert_eq!(v, [(4, 7), (1, 4)]);
+    /// let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect();
+    /// assert_eq!(v, [(4, "abc"), (1, "abc")]);
     ///
-    /// let v: Vec<(usize, usize)> = "ababa".rmatch_indices("aba").collect();
-    /// assert_eq!(v, [(2, 5)]); // only the last `aba`
+    /// let v: Vec<_> = "ababa".rmatch_indices("aba").collect();
+    /// assert_eq!(v, [(2, "aba")]); // only the last `aba`
     /// ```
-    #[unstable(feature = "str_match_indices",
-               reason = "might have its iterator type changed",
-               issue = "27743")]
-    // NB: Right now RMatchIndices yields `(usize, usize)`, but it would
-    // be more consistent with `rmatches` and `char_indices` to return `(usize, &str)`
+    #[stable(feature = "str_match_indices", since = "1.5.0")]
     pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P>
         where P::Searcher: ReverseSearcher<'a>
     {
@@ -1295,7 +1278,7 @@ impl str {
     /// repeatedly removed.
     ///
     /// The pattern can be a simple `char`, or a closure that determines
-    /// the split.
+    /// if a character matches.
     ///
     /// # Examples
     ///
@@ -1325,7 +1308,7 @@ impl str {
     /// repeatedly removed.
     ///
     /// The pattern can be a simple `&str`, `char`, or a closure that
-    /// determines the split.
+    /// determines if a character matches.
     ///
     /// # Examples
     ///
@@ -1345,7 +1328,7 @@ impl str {
     /// repeatedly removed.
     ///
     /// The pattern can be a simple `&str`, `char`, or a closure that
-    /// determines the split.
+    /// determines if a character matches.
     ///
     /// # Examples
     ///
@@ -1418,10 +1401,10 @@ impl str {
     pub fn replace(&self, from: &str, to: &str) -> String {
         let mut result = String::new();
         let mut last_end = 0;
-        for (start, end) in self.match_indices(from) {
+        for (start, part) in self.match_indices(from) {
             result.push_str(unsafe { self.slice_unchecked(last_end, start) });
             result.push_str(to);
-            last_end = end;
+            last_end = start + part.len();
         }
         result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) });
         result
index bb65d7469ab14938ecb7021f7f93ec6a2b9c9e90..96a28d3ee3ba304f9e7c438ca2d2a169f0ace2c9 100644 (file)
@@ -30,7 +30,7 @@ use vec::Vec;
 use boxed::Box;
 
 /// A growable string stored as a UTF-8 encoded buffer.
-#[derive(Clone, PartialOrd, Eq, Ord)]
+#[derive(PartialOrd, Eq, Ord)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct String {
     vec: Vec<u8>,
@@ -92,26 +92,61 @@ impl String {
         panic!("not available with cfg(test)");
     }
 
-    /// Returns the vector as a string buffer, if possible, taking care not to
-    /// copy it.
+    /// Converts a vector of bytes to a `String`.
+    ///
+    /// A string slice (`&str`) is made of bytes (`u8`), and a vector of bytes
+    /// (`Vec<u8>`) is made of bytes, so this function converts between the
+    /// two. Not all byte slices are valid `String`s, however: `String`
+    /// requires that it is valid UTF-8. `from_utf8()` checks to ensure that
+    /// the bytes are valid UTF-8, and then does the conversion.
+    ///
+    /// If you are sure that the byte slice is valid UTF-8, and you don't want
+    /// to incur the overhead of the validity check, there is an unsafe version
+    /// of this function, [`from_utf8_unchecked()`][fromutf8], which has the
+    /// same behavior but skips the check.
+    ///
+    /// [fromutf8]: struct.String.html#method.from_utf8_unchecked
+    ///
+    /// This method will take care to not copy the vector, for efficiency's
+    /// sake.
+    ///
+    /// If you need a `&str` instead of a `String`, consider
+    /// [`str::from_utf8()`][str].
+    ///
+    /// [str]: ../str/fn.from_utf8.html
     ///
     /// # Failure
     ///
-    /// If the given vector is not valid UTF-8, then the original vector and the
-    /// corresponding error is returned.
+    /// Returns `Err` if the slice is not UTF-8 with a description as to why the
+    /// provided bytes are not UTF-8. The vector you moved in is also included.
     ///
     /// # Examples
     ///
+    /// Basic usage:
+    ///
     /// ```
-    /// let hello_vec = vec![104, 101, 108, 108, 111];
-    /// let s = String::from_utf8(hello_vec).unwrap();
-    /// assert_eq!(s, "hello");
-    ///
-    /// let invalid_vec = vec![240, 144, 128];
-    /// let s = String::from_utf8(invalid_vec).err().unwrap();
-    /// let err = s.utf8_error();
-    /// assert_eq!(s.into_bytes(), [240, 144, 128]);
+    /// // some bytes, in a vector
+    /// let sparkle_heart = vec![240, 159, 146, 150];
+    ///
+    /// // We know these bytes are valid, so just use `unwrap()`.
+    /// let sparkle_heart = String::from_utf8(sparkle_heart).unwrap();
+    ///
+    /// assert_eq!("💖", sparkle_heart);
+    /// ```
+    ///
+    /// Incorrect bytes:
+    ///
     /// ```
+    /// // some invalid bytes, in a vector
+    /// let sparkle_heart = vec![0, 159, 146, 150];
+    ///
+    /// assert!(String::from_utf8(sparkle_heart).is_err());
+    /// ```
+    ///
+    /// See the docs for [`FromUtf8Error`][error] for more details on what you
+    /// can do with this error.
+    ///
+    /// [error]: struct.FromUtf8Error.html
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> {
@@ -121,15 +156,49 @@ impl String {
         }
     }
 
-    /// Converts a vector of bytes to a new UTF-8 string.
-    /// Any invalid UTF-8 sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
+    /// Converts a slice of bytes to a `String`, including invalid characters.
+    ///
+    /// A string slice (`&str`) is made of bytes (`u8`), and a slice of bytes
+    /// (`&[u8]`) is made of bytes, so this function converts between the two.
+    /// Not all byte slices are valid string slices, however: `&str` requires
+    /// that it is valid UTF-8. During this conversion, `from_utf8_lossy()`
+    /// will replace any invalid UTF-8 sequences with
+    /// `U+FFFD REPLACEMENT CHARACTER`, which looks like this: �
+    ///
+    /// If you are sure that the byte slice is valid UTF-8, and you don't want
+    /// to incur the overhead of the conversion, there is an unsafe version
+    /// of this function, [`from_utf8_unchecked()`][fromutf8], which has the
+    /// same behavior but skips the checks.
+    ///
+    /// [fromutf8]: struct.String.html#method.from_utf8_unchecked
+    ///
+    /// If you need a `&str` instead of a `String`, consider
+    /// [`str::from_utf8()`][str].
+    ///
+    /// [str]: ../str/fn.from_utf8.html
     ///
     /// # Examples
     ///
+    /// Basic usage:
+    ///
     /// ```
+    /// // some bytes, in a vector
+    /// let sparkle_heart = vec![240, 159, 146, 150];
+    ///
+    /// // We know these bytes are valid, so just use `unwrap()`.
+    /// let sparkle_heart = String::from_utf8(sparkle_heart).unwrap();
+    ///
+    /// assert_eq!("💖", sparkle_heart);
+    /// ```
+    ///
+    /// Incorrect bytes:
+    ///
+    /// ```
+    /// // some invalid bytes
     /// let input = b"Hello \xF0\x90\x80World";
     /// let output = String::from_utf8_lossy(input);
-    /// assert_eq!(output, "Hello \u{FFFD}World");
+    ///
+    /// assert_eq!("Hello �World", output);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> Cow<'a, str> {
@@ -292,7 +361,7 @@ impl String {
 
     /// Creates a new `String` from a length, capacity, and pointer.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This is _very_ unsafe because:
     ///
@@ -309,9 +378,33 @@ impl String {
         }
     }
 
-    /// Converts a vector of bytes to a new `String` without checking if
-    /// it contains valid UTF-8. This is unsafe because it assumes that
-    /// the UTF-8-ness of the vector has already been validated.
+    /// Converts a vector of bytes to a `String` without checking that the
+    /// string contains valid UTF-8.
+    ///
+    /// See the safe version, [`from_utf8()`][fromutf8], for more.
+    ///
+    /// [fromutf8]: struct.String.html#method.from_utf8
+    ///
+    /// # Safety
+    ///
+    /// This function is unsafe because it does not check that the bytes passed to
+    /// it are valid UTF-8. If this constraint is violated, undefined behavior
+    /// results, as the rest of Rust assumes that `String`s are valid UTF-8.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// // some bytes, in a vector
+    /// let sparkle_heart = vec![240, 159, 146, 150];
+    ///
+    /// let sparkle_heart = unsafe {
+    ///     String::from_utf8_unchecked(sparkle_heart)
+    /// };
+    ///
+    /// assert_eq!("💖", sparkle_heart);
+    /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String {
@@ -765,6 +858,17 @@ impl fmt::Display for FromUtf16Error {
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Clone for String {
+    fn clone(&self) -> Self {
+        String { vec: self.vec.clone() }
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        self.vec.clone_from(&source.vec);
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl FromIterator<char> for String {
     fn from_iter<I: IntoIterator<Item=char>>(iterable: I) -> String {
@@ -1027,11 +1131,9 @@ impl ops::DerefMut for String {
 }
 
 /// Error returned from `String::from`
-#[unstable(feature = "str_parse_error", reason = "may want to be replaced with \
-                                                  Void if it ever exists",
-           issue = "27734")]
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-pub struct ParseError(());
+#[stable(feature = "str_parse_error", since = "1.5.0")]
+#[derive(Copy)]
+pub enum ParseError {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl FromStr for String {
@@ -1042,6 +1144,26 @@ impl FromStr for String {
     }
 }
 
+impl Clone for ParseError {
+    fn clone(&self) -> ParseError {
+        match *self {}
+    }
+}
+
+impl fmt::Debug for ParseError {
+    fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
+        match *self {}
+    }
+}
+
+impl PartialEq for ParseError {
+    fn eq(&self, _: &ParseError) -> bool {
+        match *self {}
+    }
+}
+
+impl Eq for ParseError {}
+
 /// A generic trait for converting a value to a string
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ToString {
index c99460a55c9522a82a350c462f7837fb7b798ec4..897fea5309cb3939f92bcdf73200ce16649de9ee 100644 (file)
@@ -65,7 +65,7 @@ use alloc::heap::EMPTY;
 use core::cmp::Ordering;
 use core::fmt;
 use core::hash::{self, Hash};
-use core::intrinsics::{arith_offset, assume, drop_in_place};
+use core::intrinsics::{arith_offset, assume, drop_in_place, needs_drop};
 use core::iter::FromIterator;
 use core::mem;
 use core::ops::{Index, IndexMut, Deref};
@@ -148,6 +148,81 @@ use super::range::RangeArgument;
 /// if the vector's length is increased to 11, it will have to reallocate, which
 /// can be slow. For this reason, it is recommended to use `Vec::with_capacity`
 /// whenever possible to specify how big the vector is expected to get.
+///
+/// # Guarantees
+///
+/// Due to its incredibly fundamental nature, Vec makes a lot of guarantees
+/// about its design. This ensures that it's as low-overhead as possible in
+/// the general case, and can be correctly manipulated in primitive ways
+/// by unsafe code. Note that these guarantees refer to an unqualified `Vec<T>`.
+/// If additional type parameters are added (e.g. to support custom allocators),
+/// overriding their defaults may change the behavior.
+///
+/// Most fundamentally, Vec is and always will be a (pointer, capacity, length)
+/// triplet. No more, no less. The order of these fields is completely
+/// unspecified, and you should use the appropriate methods to modify these.
+/// The pointer will never be null, so this type is null-pointer-optimized.
+///
+/// However, the pointer may not actually point to allocated memory. In particular,
+/// if you construct a Vec with capacity 0 via `Vec::new()`, `vec![]`,
+/// `Vec::with_capacity(0)`, or by calling `shrink_to_fit()` on an empty Vec, it
+/// will not allocate memory. Similarly, if you store zero-sized types inside
+/// a Vec, it will not allocate space for them. *Note that in this case the
+/// Vec may not report a `capacity()` of 0*. Vec will allocate if and only
+/// if `mem::size_of::<T>() * capacity() > 0`. In general, Vec's allocation
+/// details are subtle enough that it is strongly recommended that you only
+/// free memory allocated by a Vec by creating a new Vec and dropping it.
+///
+/// If a Vec *has* allocated memory, then the memory it points to is on the heap
+/// (as defined by the allocator Rust is configured to use by default), and its
+/// pointer points to `len()` initialized elements in order (what you would see
+/// if you coerced it to a slice), followed by `capacity() - len()` logically
+/// uninitialized elements.
+///
+/// Vec will never perform a "small optimization" where elements are actually
+/// stored on the stack for two reasons:
+///
+/// * It would make it more difficult for unsafe code to correctly manipulate
+///   a Vec. The contents of a Vec wouldn't have a stable address if it were
+///   only moved, and it would be more difficult to determine if a Vec had
+///   actually allocated memory.
+///
+/// * It would penalize the general case, incurring an additional branch
+///   on every access.
+///
+/// Vec will never automatically shrink itself, even if completely empty. This
+/// ensures no unnecessary allocations or deallocations occur. Emptying a Vec
+/// and then filling it back up to the same `len()` should incur no calls to
+/// the allocator. If you wish to free up unused memory, use `shrink_to_fit`.
+///
+/// `push` and `insert` will never (re)allocate if the reported capacity is
+/// sufficient. `push` and `insert` *will* (re)allocate if `len() == capacity()`.
+/// That is, the reported capacity is completely accurate, and can be relied on.
+/// It can even be used to manually free the memory allocated by a Vec if
+/// desired. Bulk insertion methods *may* reallocate, even when not necessary.
+///
+/// Vec does not guarantee any particular growth strategy when reallocating
+/// when full, nor when `reserve` is called. The current strategy is basic
+/// and it may prove desirable to use a non-constant growth factor. Whatever
+/// strategy is used will of course guarantee `O(1)` amortized `push`.
+///
+/// `vec![x; n]`, `vec![a, b, c, d]`, and `Vec::with_capacity(n)`, will all
+/// produce a Vec with exactly the requested capacity. If `len() == capacity()`,
+/// (as is the case for the `vec!` macro), then a `Vec<T>` can be converted
+/// to and from a `Box<[T]>` without reallocating or moving the elements.
+///
+/// Vec will not specifically overwrite any data that is removed from it,
+/// but also won't specifically preserve it. Its uninitialized memory is
+/// scratch space that it may use however it wants. It will generally just do
+/// whatever is most efficient or otherwise easy to implement. Do not rely on
+/// removed data to be erased for security purposes. Even if you drop a Vec, its
+/// buffer may simply be reused by another Vec. Even if you zero a Vec's memory
+/// first, that may not actually happen because the optimizer does not consider
+/// this a side-effect that must be preserved.
+///
+/// Vec does not currently guarantee the order in which elements are dropped
+/// (the order has changed in the past, and may change again).
+///
 #[unsafe_no_drop_flag]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Vec<T> {
@@ -209,7 +284,7 @@ impl<T> Vec<T> {
 
     /// Creates a `Vec<T>` directly from the raw components of another vector.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This is highly unsafe, due to the number of invariants that aren't
     /// checked:
@@ -753,8 +828,6 @@ impl<T> Vec<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(split_off)]
-    ///
     /// let mut vec = vec![1,2,3];
     /// let vec2 = vec.split_off(1);
     /// assert_eq!(vec, [1]);
@@ -792,8 +865,6 @@ impl<T: Clone> Vec<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(vec_resize)]
-    ///
     /// let mut vec = vec!["hello"];
     /// vec.resize(3, "world");
     /// assert_eq!(vec, ["hello", "world", "world"]);
@@ -802,9 +873,7 @@ impl<T: Clone> Vec<T> {
     /// vec.resize(2, 0);
     /// assert_eq!(vec, [1, 2]);
     /// ```
-    #[unstable(feature = "vec_resize",
-               reason = "matches collection reform specification; waiting for dust to settle",
-               issue = "27790")]
+    #[stable(feature = "vec_resize", since = "1.5.0")]
     pub fn resize(&mut self, new_len: usize, value: T) {
         let len = self.len();
 
@@ -1007,19 +1076,15 @@ impl<T:Clone> Clone for Vec<T> {
 
     fn clone_from(&mut self, other: &Vec<T>) {
         // drop anything in self that will not be overwritten
-        if self.len() > other.len() {
-            self.truncate(other.len())
-        }
+        self.truncate(other.len());
+        let len = self.len();
 
         // reuse the contained values' allocations/resources.
-        for (place, thing) in self.iter_mut().zip(other) {
-            place.clone_from(thing)
-        }
+        self.clone_from_slice(&other[..len]);
 
         // self.len <= other.len due to the truncate above, so the
         // slice here is always in-bounds.
-        let slice = &other[self.len()..];
-        self.push_all(slice);
+        self.push_all(&other[len..]);
     }
 }
 
@@ -1316,14 +1381,21 @@ impl<T: Ord> Ord for Vec<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Vec<T> {
+    #[unsafe_destructor_blind_to_params]
     fn drop(&mut self) {
         // NOTE: this is currently abusing the fact that ZSTs can't impl Drop.
         // Or rather, that impl'ing Drop makes them not zero-sized. This is
         // OK because exactly when this stops being a valid assumption, we
         // don't need unsafe_no_drop_flag shenanigans anymore.
         if self.buf.unsafe_no_drop_flag_needs_drop() {
-            for x in self.iter_mut() {
-                unsafe { drop_in_place(x); }
+            unsafe {
+                // The branch on needs_drop() is an -O1 performance optimization.
+                // Without the branch, dropping Vec<u8> takes linear time.
+                if needs_drop::<T>() {
+                    for x in self.iter_mut() {
+                        drop_in_place(x);
+                    }
+                }
             }
         }
         // RawVec handles deallocation
@@ -1352,6 +1424,13 @@ impl<T> AsRef<Vec<T>> for Vec<T> {
     }
 }
 
+#[stable(feature = "vec_as_mut", since = "1.5.0")]
+impl<T> AsMut<Vec<T>> for Vec<T> {
+    fn as_mut(&mut self) -> &mut Vec<T> {
+        self
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> AsRef<[T]> for Vec<T> {
     fn as_ref(&self) -> &[T] {
@@ -1359,6 +1438,13 @@ impl<T> AsRef<[T]> for Vec<T> {
     }
 }
 
+#[stable(feature = "vec_as_mut", since = "1.5.0")]
+impl<T> AsMut<[T]> for Vec<T> {
+    fn as_mut(&mut self) -> &mut [T] {
+        self
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: Clone> From<&'a [T]> for Vec<T> {
     #[cfg(not(test))]
@@ -1487,9 +1573,10 @@ impl<T> ExactSizeIterator for IntoIter<T> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for IntoIter<T> {
+    #[unsafe_destructor_blind_to_params]
     fn drop(&mut self) {
         // destroy the remaining elements
-        for _x in self.by_ref() {}
+        for _x in self {}
 
         // RawVec handles deallocation
     }
index 4ee9787c9ec8a5c727bf93d2059e04436d79e7d3..937ace00fdcca819f11147a24f74803c65723009 100644 (file)
@@ -32,16 +32,19 @@ use core::cmp;
 
 use alloc::raw_vec::RawVec;
 
+use super::range::RangeArgument;
+
 const INITIAL_CAPACITY: usize = 7; // 2^3 - 1
 const MINIMUM_CAPACITY: usize = 1; // 2 - 1
 const MAXIMUM_ZST_CAPACITY: usize = 1 << (usize::BITS - 1); // Largest possible power of two
 
-/// `VecDeque` is a growable ring buffer, which can be used as a
-/// double-ended queue efficiently.
+/// `VecDeque` is a growable ring buffer, which can be used as a double-ended
+/// queue efficiently.
 ///
-/// The "default" usage of this type as a queue is to use `push_back` to add to the queue, and
-/// `pop_front` to remove from the queue. `extend` and `append` push onto the back in this manner,
-/// and iterating over `VecDeque` goes front to back.
+/// The "default" usage of this type as a queue is to use `push_back` to add to
+/// the queue, and `pop_front` to remove from the queue. `extend` and `append`
+/// push onto the back in this manner, and iterating over `VecDeque` goes front
+/// to back.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct VecDeque<T> {
     // tail and head are pointers into the buffer. Tail always points
@@ -64,6 +67,7 @@ impl<T: Clone> Clone for VecDeque<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for VecDeque<T> {
+    #[unsafe_destructor_blind_to_params]
     fn drop(&mut self) {
         self.clear();
         // RawVec handles deallocation
@@ -167,6 +171,117 @@ impl<T> VecDeque<T> {
             len);
     }
 
+    /// Copies a potentially wrapping block of memory len long from src to dest.
+    /// (abs(dst - src) + len) must be no larger than cap() (There must be at
+    /// most one continuous overlapping region between src and dest).
+    unsafe fn wrap_copy(&self, dst: usize, src: usize, len: usize) {
+        debug_assert!(
+            (if src <= dst { dst - src } else { src - dst }) + len <= self.cap(),
+            "dst={} src={} len={} cap={}", dst, src, len, self.cap());
+
+        if src == dst || len == 0 { return }
+
+        let dst_after_src = self.wrap_sub(dst, src) < len;
+
+        let src_pre_wrap_len = self.cap() - src;
+        let dst_pre_wrap_len = self.cap() - dst;
+        let src_wraps = src_pre_wrap_len < len;
+        let dst_wraps = dst_pre_wrap_len < len;
+
+        match (dst_after_src, src_wraps, dst_wraps) {
+            (_, false, false) => {
+                // src doesn't wrap, dst doesn't wrap
+                //
+                //        S . . .
+                // 1 [_ _ A A B B C C _]
+                // 2 [_ _ A A A A B B _]
+                //            D . . .
+                //
+                self.copy(dst, src, len);
+            }
+            (false, false, true) => {
+                // dst before src, src doesn't wrap, dst wraps
+                //
+                //    S . . .
+                // 1 [A A B B _ _ _ C C]
+                // 2 [A A B B _ _ _ A A]
+                // 3 [B B B B _ _ _ A A]
+                //    . .           D .
+                //
+                self.copy(dst, src, dst_pre_wrap_len);
+                self.copy(0, src + dst_pre_wrap_len, len - dst_pre_wrap_len);
+            }
+            (true, false, true) => {
+                // src before dst, src doesn't wrap, dst wraps
+                //
+                //              S . . .
+                // 1 [C C _ _ _ A A B B]
+                // 2 [B B _ _ _ A A B B]
+                // 3 [B B _ _ _ A A A A]
+                //    . .           D .
+                //
+                self.copy(0, src + dst_pre_wrap_len, len - dst_pre_wrap_len);
+                self.copy(dst, src, dst_pre_wrap_len);
+            }
+            (false, true, false) => {
+                // dst before src, src wraps, dst doesn't wrap
+                //
+                //    . .           S .
+                // 1 [C C _ _ _ A A B B]
+                // 2 [C C _ _ _ B B B B]
+                // 3 [C C _ _ _ B B C C]
+                //              D . . .
+                //
+                self.copy(dst, src, src_pre_wrap_len);
+                self.copy(dst + src_pre_wrap_len, 0, len - src_pre_wrap_len);
+            }
+            (true, true, false) => {
+                // src before dst, src wraps, dst doesn't wrap
+                //
+                //    . .           S .
+                // 1 [A A B B _ _ _ C C]
+                // 2 [A A A A _ _ _ C C]
+                // 3 [C C A A _ _ _ C C]
+                //    D . . .
+                //
+                self.copy(dst + src_pre_wrap_len, 0, len - src_pre_wrap_len);
+                self.copy(dst, src, src_pre_wrap_len);
+            }
+            (false, true, true) => {
+                // dst before src, src wraps, dst wraps
+                //
+                //    . . .         S .
+                // 1 [A B C D _ E F G H]
+                // 2 [A B C D _ E G H H]
+                // 3 [A B C D _ E G H A]
+                // 4 [B C C D _ E G H A]
+                //    . .         D . .
+                //
+                debug_assert!(dst_pre_wrap_len > src_pre_wrap_len);
+                let delta = dst_pre_wrap_len - src_pre_wrap_len;
+                self.copy(dst, src, src_pre_wrap_len);
+                self.copy(dst + src_pre_wrap_len, 0, delta);
+                self.copy(0, delta, len - dst_pre_wrap_len);
+            }
+            (true, true, true) => {
+                // src before dst, src wraps, dst wraps
+                //
+                //    . .         S . .
+                // 1 [A B C D _ E F G H]
+                // 2 [A A B D _ E F G H]
+                // 3 [H A B D _ E F G H]
+                // 4 [H A B D _ E F F G]
+                //    . . .         D .
+                //
+                debug_assert!(src_pre_wrap_len > dst_pre_wrap_len);
+                let delta = src_pre_wrap_len - dst_pre_wrap_len;
+                self.copy(delta, 0, len - src_pre_wrap_len);
+                self.copy(0, self.cap() - delta, delta);
+                self.copy(dst, src, dst_pre_wrap_len);
+            }
+        }
+    }
+
     /// Frobs the head and tail sections around to handle the fact that we
     /// just reallocated. Unsafe because it trusts old_cap.
     #[inline]
@@ -385,8 +500,6 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(deque_extras)]
-    ///
     /// use std::collections::VecDeque;
     ///
     /// let mut buf = VecDeque::with_capacity(15);
@@ -395,9 +508,7 @@ impl<T> VecDeque<T> {
     /// buf.shrink_to_fit();
     /// assert!(buf.capacity() >= 4);
     /// ```
-    #[unstable(feature = "deque_extras",
-               reason = "needs to be audited",
-               issue = "27788")]
+    #[stable(feature = "deque_extras_15", since = "1.5.0")]
     pub fn shrink_to_fit(&mut self) {
         // +1 since the ringbuffer always leaves one space empty
         // len + 1 can't overflow for an existing, well-formed ringbuffer.
@@ -539,9 +650,7 @@ impl<T> VecDeque<T> {
     /// Returns a pair of slices which contain, in order, the contents of the
     /// `VecDeque`.
     #[inline]
-    #[unstable(feature = "deque_extras",
-               reason = "matches collection reform specification, waiting for dust to settle",
-               issue = "27788")]
+    #[stable(feature = "deque_extras_15", since = "1.5.0")]
     pub fn as_slices(&self) -> (&[T], &[T]) {
         unsafe {
             let contiguous = self.is_contiguous();
@@ -560,9 +669,7 @@ impl<T> VecDeque<T> {
     /// Returns a pair of slices which contain, in order, the contents of the
     /// `VecDeque`.
     #[inline]
-    #[unstable(feature = "deque_extras",
-               reason = "matches collection reform specification, waiting for dust to settle",
-               issue = "27788")]
+    #[stable(feature = "deque_extras_15", since = "1.5.0")]
     pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
         unsafe {
             let contiguous = self.is_contiguous();
@@ -612,8 +719,18 @@ impl<T> VecDeque<T> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
-    /// Creates a draining iterator that clears the `VecDeque` and iterates over
-    /// the removed items from start to end.
+    /// Create a draining iterator that removes the specified range in the
+    /// `VecDeque` and yields the removed items from start to end. The element
+    /// range is removed even if the iterator is not consumed until the end.
+    ///
+    /// Note: It is unspecified how many elements are removed from the deque,
+    /// if the `Drain` value is not dropped, but the borrow it holds expires
+    /// (eg. due to mem::forget).
+    ///
+    /// # Panics
+    ///
+    /// Panics if the starting point is greater than the end point or if
+    /// the end point is greater than the length of the vector.
     ///
     /// # Examples
     ///
@@ -622,18 +739,66 @@ impl<T> VecDeque<T> {
     ///
     /// use std::collections::VecDeque;
     ///
+    /// // draining using `..` clears the whole deque.
     /// let mut v = VecDeque::new();
     /// v.push_back(1);
-    /// assert_eq!(v.drain().next(), Some(1));
+    /// assert_eq!(v.drain(..).next(), Some(1));
     /// assert!(v.is_empty());
     /// ```
     #[inline]
     #[unstable(feature = "drain",
                reason = "matches collection reform specification, waiting for dust to settle",
                issue = "27711")]
-    pub fn drain(&mut self) -> Drain<T> {
+    pub fn drain<R>(&mut self, range: R) -> Drain<T> where R: RangeArgument<usize> {
+        // Memory safety
+        //
+        // When the Drain is first created, the source deque is shortened to
+        // make sure no uninitialized or moved-from elements are accessible at
+        // all if the Drain's destructor never gets to run.
+        //
+        // Drain will ptr::read out the values to remove.
+        // When finished, the remaining data will be copied back to cover the hole,
+        // and the head/tail values will be restored correctly.
+        //
+        let len = self.len();
+        let start = *range.start().unwrap_or(&0);
+        let end = *range.end().unwrap_or(&len);
+        assert!(start <= end, "drain lower bound was too large");
+        assert!(end <= len, "drain upper bound was too large");
+
+        // The deque's elements are parted into three segments:
+        // * self.tail  -> drain_tail
+        // * drain_tail -> drain_head
+        // * drain_head -> self.head
+        //
+        // T = self.tail; H = self.head; t = drain_tail; h = drain_head
+        //
+        // We store drain_tail as self.head, and drain_head and self.head as
+        // after_tail and after_head respectively on the Drain. This also
+        // truncates the effective array such that if the Drain is leaked, we
+        // have forgotten about the potentially moved values after the start of
+        // the drain.
+        //
+        //        T   t   h   H
+        // [. . . o o x x o o . . .]
+        //
+        let drain_tail = self.wrap_add(self.tail, start);
+        let drain_head = self.wrap_add(self.tail, end);
+        let head = self.head;
+
+        // "forget" about the values after the start of the drain until after
+        // the drain is complete and the Drain destructor is run.
+        self.head = drain_tail;
+
         Drain {
-            inner: self,
+            deque: self as *mut _,
+            after_tail: drain_head,
+            after_head: head,
+            iter: Iter {
+                tail: drain_tail,
+                head: drain_head,
+                ring: unsafe { self.buffer_as_mut_slice() },
+            },
         }
     }
 
@@ -652,7 +817,7 @@ impl<T> VecDeque<T> {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn clear(&mut self) {
-        self.drain();
+        self.drain(..);
     }
 
     /// Provides a reference to the front element, or `None` if the sequence is
@@ -863,25 +1028,21 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(deque_extras)]
-    ///
     /// use std::collections::VecDeque;
     ///
     /// let mut buf = VecDeque::new();
-    /// assert_eq!(buf.swap_back_remove(0), None);
+    /// assert_eq!(buf.swap_remove_back(0), None);
     /// buf.push_back(1);
     /// buf.push_back(2);
     /// buf.push_back(3);
     ///
-    /// assert_eq!(buf.swap_back_remove(0), Some(1));
+    /// assert_eq!(buf.swap_remove_back(0), Some(1));
     /// assert_eq!(buf.len(), 2);
     /// assert_eq!(buf[0], 3);
     /// assert_eq!(buf[1], 2);
     /// ```
-    #[unstable(feature = "deque_extras",
-               reason = "the naming of this function may be altered",
-               issue = "27788")]
-    pub fn swap_back_remove(&mut self, index: usize) -> Option<T> {
+    #[stable(feature = "deque_extras_15", since = "1.5.0")]
+    pub fn swap_remove_back(&mut self, index: usize) -> Option<T> {
         let length = self.len();
         if length > 0 && index < length - 1 {
             self.swap(index, length - 1);
@@ -891,6 +1052,15 @@ impl<T> VecDeque<T> {
         self.pop_back()
     }
 
+    /// deprecated
+    #[unstable(feature = "deque_extras",
+               reason = "the naming of this function may be altered",
+               issue = "27788")]
+    #[deprecated(since = "1.5.0", reason = "renamed to swap_remove_back")]
+    pub fn swap_back_remove(&mut self, index: usize) -> Option<T> {
+        self.swap_remove_back(index)
+    }
+
     /// Removes an element from anywhere in the `VecDeque` and returns it,
     /// replacing it with the first element.
     ///
@@ -901,25 +1071,21 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(deque_extras)]
-    ///
     /// use std::collections::VecDeque;
     ///
     /// let mut buf = VecDeque::new();
-    /// assert_eq!(buf.swap_front_remove(0), None);
+    /// assert_eq!(buf.swap_remove_front(0), None);
     /// buf.push_back(1);
     /// buf.push_back(2);
     /// buf.push_back(3);
     ///
-    /// assert_eq!(buf.swap_front_remove(2), Some(3));
+    /// assert_eq!(buf.swap_remove_front(2), Some(3));
     /// assert_eq!(buf.len(), 2);
     /// assert_eq!(buf[0], 2);
     /// assert_eq!(buf[1], 1);
     /// ```
-    #[unstable(feature = "deque_extras",
-               reason = "the naming of this function may be altered",
-               issue = "27788")]
-    pub fn swap_front_remove(&mut self, index: usize) -> Option<T> {
+    #[stable(feature = "deque_extras_15", since = "1.5.0")]
+    pub fn swap_remove_front(&mut self, index: usize) -> Option<T> {
         let length = self.len();
         if length > 0 && index < length && index != 0 {
             self.swap(index, 0);
@@ -929,6 +1095,15 @@ impl<T> VecDeque<T> {
         self.pop_front()
     }
 
+    /// deprecated
+    #[unstable(feature = "deque_extras",
+               reason = "the naming of this function may be altered",
+               issue = "27788")]
+    #[deprecated(since = "1.5.0", reason = "renamed to swap_remove_front")]
+    pub fn swap_front_remove(&mut self, index: usize) -> Option<T> {
+        self.swap_remove_front(index)
+    }
+
     /// Inserts an element at `index` within the `VecDeque`. Whichever
     /// end is closer to the insertion point will be moved to make room,
     /// and all the affected elements will be moved to new positions.
@@ -939,8 +1114,6 @@ impl<T> VecDeque<T> {
     ///
     /// # Examples
     /// ```
-    /// #![feature(deque_extras)]
-    ///
     /// use std::collections::VecDeque;
     ///
     /// let mut buf = VecDeque::new();
@@ -949,9 +1122,7 @@ impl<T> VecDeque<T> {
     /// buf.insert(1, 11);
     /// assert_eq!(Some(&11), buf.get(1));
     /// ```
-    #[unstable(feature = "deque_extras",
-               reason = "needs to be audited",
-               issue = "27788")]
+    #[stable(feature = "deque_extras_15", since = "1.5.0")]
     pub fn insert(&mut self, index: usize, value: T) {
         assert!(index <= self.len(), "index out of bounds");
         if self.is_full() {
@@ -1319,8 +1490,6 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(split_off)]
-    ///
     /// use std::collections::VecDeque;
     ///
     /// let mut buf: VecDeque<_> = vec![1,2,3].into_iter().collect();
@@ -1394,7 +1563,7 @@ impl<T> VecDeque<T> {
     #[stable(feature = "append", since = "1.4.0")]
     pub fn append(&mut self, other: &mut Self) {
         // naive impl
-        self.extend(other.drain());
+        self.extend(other.drain(..));
     }
 
     /// Retains only the elements specified by the predicate.
@@ -1406,8 +1575,6 @@ impl<T> VecDeque<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(vec_deque_retain)]
-    ///
     /// use std::collections::VecDeque;
     ///
     /// let mut buf = VecDeque::new();
@@ -1630,15 +1797,59 @@ impl<T> ExactSizeIterator for IntoIter<T> {}
            reason = "matches collection reform specification, waiting for dust to settle",
            issue = "27711")]
 pub struct Drain<'a, T: 'a> {
-    inner: &'a mut VecDeque<T>,
+    after_tail: usize,
+    after_head: usize,
+    iter: Iter<'a, T>,
+    deque: *mut VecDeque<T>,
 }
 
+unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {}
+unsafe impl<'a, T: Send> Send for Drain<'a, T> {}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: 'a> Drop for Drain<'a, T> {
     fn drop(&mut self) {
         for _ in self.by_ref() {}
-        self.inner.head = 0;
-        self.inner.tail = 0;
+
+        let source_deque = unsafe { &mut *self.deque };
+
+        // T = source_deque_tail; H = source_deque_head; t = drain_tail; h = drain_head
+        //
+        //        T   t   h   H
+        // [. . . o o x x o o . . .]
+        //
+        let orig_tail = source_deque.tail;
+        let drain_tail = source_deque.head;
+        let drain_head = self.after_tail;
+        let orig_head = self.after_head;
+
+        let tail_len = count(orig_tail, drain_tail, source_deque.cap());
+        let head_len = count(drain_head, orig_head, source_deque.cap());
+
+        // Restore the original head value
+        source_deque.head = orig_head;
+
+        match (tail_len, head_len) {
+            (0, 0) => {
+                source_deque.head = 0;
+                source_deque.tail = 0;
+            }
+            (0, _) => {
+                source_deque.tail = drain_head;
+            }
+            (_, 0) => {
+                source_deque.head = drain_tail;
+            }
+            _ => unsafe {
+                if tail_len <= head_len {
+                    source_deque.tail = source_deque.wrap_sub(drain_head, tail_len);
+                    source_deque.wrap_copy(source_deque.tail, orig_tail, tail_len);
+                } else {
+                    source_deque.head = source_deque.wrap_add(drain_tail, head_len);
+                    source_deque.wrap_copy(drain_tail, drain_head, head_len);
+                }
+            }
+        }
     }
 }
 
@@ -1648,13 +1859,16 @@ impl<'a, T: 'a> Iterator for Drain<'a, T> {
 
     #[inline]
     fn next(&mut self) -> Option<T> {
-        self.inner.pop_front()
+        self.iter.next().map(|elt|
+            unsafe {
+                ptr::read(elt)
+            }
+        )
     }
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        let len = self.inner.len();
-        (len, Some(len))
+        self.iter.size_hint()
     }
 }
 
@@ -1662,7 +1876,11 @@ impl<'a, T: 'a> Iterator for Drain<'a, T> {
 impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<T> {
-        self.inner.pop_back()
+        self.iter.next_back().map(|elt|
+            unsafe {
+                ptr::read(elt)
+            }
+        )
     }
 }
 
@@ -1787,14 +2005,7 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for VecDeque<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: fmt::Debug> fmt::Debug for VecDeque<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "["));
-
-        for (i, e) in self.iter().enumerate() {
-            if i != 0 { try!(write!(f, ", ")); }
-            try!(write!(f, "{:?}", *e));
-        }
-
-        write!(f, "]")
+        f.debug_list().entries(self).finish()
     }
 }
 
@@ -1972,6 +2183,44 @@ mod tests {
         }
     }
 
+    #[test]
+    fn test_drain() {
+        let mut tester: VecDeque<usize> = VecDeque::with_capacity(7);
+
+        let cap = tester.capacity();
+        for len in 0..cap + 1 {
+            for tail in 0..cap + 1 {
+                for drain_start in 0..len + 1 {
+                    for drain_end in drain_start..len + 1 {
+                        tester.tail = tail;
+                        tester.head = tail;
+                        for i in 0..len {
+                            tester.push_back(i);
+                        }
+
+                        // Check that we drain the correct values
+                        let drained: VecDeque<_> =
+                            tester.drain(drain_start..drain_end).collect();
+                        let drained_expected: VecDeque<_> =
+                            (drain_start..drain_end).collect();
+                        assert_eq!(drained, drained_expected);
+
+                        // We shouldn't have changed the capacity or made the
+                        // head or tail out of bounds
+                        assert_eq!(tester.capacity(), cap);
+                        assert!(tester.tail < tester.cap());
+                        assert!(tester.head < tester.cap());
+
+                        // We should see the correct values in the VecDeque
+                        let expected: VecDeque<_> =
+                            (0..drain_start).chain(drain_end..len).collect();
+                        assert_eq!(expected, tester);
+                    }
+                }
+            }
+        }
+    }
+
     #[test]
     fn test_shrink_to_fit() {
         // This test checks that every single combination of head and tail position,
index 62b46433da95748ae6ba7d5c2ea37a5046968f03..846353cc4e7c29abe36aad462e14b1d5bc8095c3 100644 (file)
@@ -294,6 +294,59 @@ fn test_extend_ref() {
     assert_eq!(a[&3], "three");
 }
 
+#[test]
+fn test_zst() {
+    let mut m = BTreeMap::new();
+    assert_eq!(m.len(), 0);
+
+    assert_eq!(m.insert((), ()), None);
+    assert_eq!(m.len(), 1);
+
+    assert_eq!(m.insert((), ()), Some(()));
+    assert_eq!(m.len(), 1);
+    assert_eq!(m.iter().count(), 1);
+
+    m.clear();
+    assert_eq!(m.len(), 0);
+
+    for _ in 0..100 {
+        m.insert((), ());
+    }
+
+    assert_eq!(m.len(), 1);
+    assert_eq!(m.iter().count(), 1);
+}
+
+// This test's only purpose is to ensure that zero-sized keys with nonsensical orderings
+// do not cause segfaults when used with zero-sized values. All other map behavior is
+// undefined.
+#[test]
+fn test_bad_zst() {
+    use std::cmp::Ordering;
+
+    struct Bad;
+
+    impl PartialEq for Bad {
+        fn eq(&self, _: &Self) -> bool { false }
+    }
+
+    impl Eq for Bad {}
+
+    impl PartialOrd for Bad {
+        fn partial_cmp(&self, _: &Self) -> Option<Ordering> { Some(Ordering::Less) }
+    }
+
+    impl Ord for Bad {
+        fn cmp(&self, _: &Self) -> Ordering { Ordering::Less }
+    }
+
+    let mut m = BTreeMap::new();
+
+    for _ in 0..100 {
+        m.insert(Bad, Bad);
+    }
+}
+
 mod bench {
     use std::collections::BTreeMap;
     use std::__rand::{Rng, thread_rng};
index e7593bfcfe55634e230f611013608e1f3199fed9..8fcfe97f42afcb2fcc029c8f1a1e418139a7a05d 100644 (file)
@@ -148,15 +148,9 @@ fn test_zip() {
     let y = y;
     let mut z = x.iter().zip(&y);
 
-    // FIXME: #5801: this needs a type hint to compile...
-    let result: Option<(&usize, & &'static str)> = z.next();
-    assert_eq!(result.unwrap(), (&5, &("bar")));
-
-    let result: Option<(&usize, & &'static str)> = z.next();
-    assert_eq!(result.unwrap(), (&11, &("foo")));
-
-    let result: Option<(&usize, & &'static str)> = z.next();
-    assert!(result.is_none());
+    assert_eq!(z.next().unwrap(), (&5, &("bar")));
+    assert_eq!(z.next().unwrap(), (&11, &("foo")));
+    assert!(z.next().is_none());
 }
 
 #[test]
index d84f5bdf10785557410b72dd726a036b992d3d64..63c7bc15c8fc66f7adb46df4e8ad04cd2ada78ab 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![feature(ascii)]
-#![feature(append)]
 #![feature(binary_heap_extras)]
 #![feature(box_syntax)]
 #![feature(btree_range)]
 #![feature(set_recovery)]
 #![feature(slice_bytes)]
 #![feature(slice_splits)]
-#![feature(split_off)]
 #![feature(step_by)]
 #![feature(str_char)]
 #![feature(str_escape)]
 #![feature(str_match_indices)]
-#![feature(str_split_at)]
 #![feature(str_utf16)]
-#![feature(box_str)]
 #![feature(test)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
-#![feature(vec_deque_retain)]
 #![feature(vec_push_all)]
 
 #[macro_use] extern crate log;
index 7b481f63991165d04e3e3a6357753f1a45ff6f57..e22ff7ca540610335c22e1b1705d9213c07d1851 100644 (file)
@@ -41,10 +41,10 @@ fn test_rfind() {
 
 #[test]
 fn test_collect() {
-    let empty = String::from("");
+    let empty = "";
     let s: String = empty.chars().collect();
     assert_eq!(empty, s);
-    let data = String::from("ประเทศไทย中");
+    let data = "ประเทศไทย中";
     let s: String = data.chars().collect();
     assert_eq!(data, s);
 }
@@ -86,7 +86,7 @@ fn test_find_str() {
     assert_eq!(data[43..86].find("iệt"), Some(77 - 43));
     assert_eq!(data[43..86].find("Nam"), Some(83 - 43));
 
-    // find every substring -- assert that it finds it, or an earlier occurence.
+    // find every substring -- assert that it finds it, or an earlier occurrence.
     let string = "Việt Namacbaabcaabaaba";
     for (i, ci) in string.char_indices() {
         let ip = i + ci.len_utf8();
@@ -187,10 +187,8 @@ fn test_unsafe_slice() {
         rs
     }
     let letters = a_million_letter_a();
-    assert!(half_a_million_letter_a() ==
-        unsafe {String::from(letters.slice_unchecked(
-                                 0,
-                                 500000))});
+    assert_eq!(half_a_million_letter_a(),
+        unsafe { letters.slice_unchecked(0, 500000)});
 }
 
 #[test]
@@ -224,13 +222,12 @@ fn test_is_empty() {
 #[test]
 fn test_replace() {
     let a = "a";
-    assert_eq!("".replace(a, "b"), String::from(""));
-    assert_eq!("a".replace(a, "b"), String::from("b"));
-    assert_eq!("ab".replace(a, "b"), String::from("bb"));
+    assert_eq!("".replace(a, "b"), "");
+    assert_eq!("a".replace(a, "b"), "b");
+    assert_eq!("ab".replace(a, "b"), "bb");
     let test = "test";
-    assert!(" test test ".replace(test, "toast") ==
-        String::from(" toast toast "));
-    assert_eq!(" test test ".replace(test, ""), String::from("   "));
+    assert_eq!(" test test ".replace(test, "toast"), " toast toast ");
+    assert_eq!(" test test ".replace(test, ""), "   ");
 }
 
 #[test]
@@ -304,8 +301,7 @@ fn test_slice() {
         rs
     }
     let letters = a_million_letter_x();
-    assert!(half_a_million_letter_x() ==
-        String::from(&letters[0..3 * 500000]));
+    assert_eq!(half_a_million_letter_x(), &letters[0..3 * 500000]);
 }
 
 #[test]
@@ -676,49 +672,36 @@ fn test_split_at_boundscheck() {
 
 #[test]
 fn test_escape_unicode() {
-    assert_eq!("abc".escape_unicode(),
-               String::from("\\u{61}\\u{62}\\u{63}"));
-    assert_eq!("a c".escape_unicode(),
-               String::from("\\u{61}\\u{20}\\u{63}"));
-    assert_eq!("\r\n\t".escape_unicode(),
-               String::from("\\u{d}\\u{a}\\u{9}"));
-    assert_eq!("'\"\\".escape_unicode(),
-               String::from("\\u{27}\\u{22}\\u{5c}"));
-    assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(),
-               String::from("\\u{0}\\u{1}\\u{fe}\\u{ff}"));
-    assert_eq!("\u{100}\u{ffff}".escape_unicode(),
-               String::from("\\u{100}\\u{ffff}"));
-    assert_eq!("\u{10000}\u{10ffff}".escape_unicode(),
-               String::from("\\u{10000}\\u{10ffff}"));
-    assert_eq!("ab\u{fb00}".escape_unicode(),
-               String::from("\\u{61}\\u{62}\\u{fb00}"));
-    assert_eq!("\u{1d4ea}\r".escape_unicode(),
-               String::from("\\u{1d4ea}\\u{d}"));
+    assert_eq!("abc".escape_unicode(), "\\u{61}\\u{62}\\u{63}");
+    assert_eq!("a c".escape_unicode(), "\\u{61}\\u{20}\\u{63}");
+    assert_eq!("\r\n\t".escape_unicode(), "\\u{d}\\u{a}\\u{9}");
+    assert_eq!("'\"\\".escape_unicode(), "\\u{27}\\u{22}\\u{5c}");
+    assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
+    assert_eq!("\u{100}\u{ffff}".escape_unicode(), "\\u{100}\\u{ffff}");
+    assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), "\\u{10000}\\u{10ffff}");
+    assert_eq!("ab\u{fb00}".escape_unicode(), "\\u{61}\\u{62}\\u{fb00}");
+    assert_eq!("\u{1d4ea}\r".escape_unicode(), "\\u{1d4ea}\\u{d}");
 }
 
 #[test]
 fn test_escape_default() {
-    assert_eq!("abc".escape_default(), String::from("abc"));
-    assert_eq!("a c".escape_default(), String::from("a c"));
-    assert_eq!("\r\n\t".escape_default(), String::from("\\r\\n\\t"));
-    assert_eq!("'\"\\".escape_default(), String::from("\\'\\\"\\\\"));
-    assert_eq!("\u{100}\u{ffff}".escape_default(),
-               String::from("\\u{100}\\u{ffff}"));
-    assert_eq!("\u{10000}\u{10ffff}".escape_default(),
-               String::from("\\u{10000}\\u{10ffff}"));
-    assert_eq!("ab\u{fb00}".escape_default(),
-               String::from("ab\\u{fb00}"));
-    assert_eq!("\u{1d4ea}\r".escape_default(),
-               String::from("\\u{1d4ea}\\r"));
+    assert_eq!("abc".escape_default(), "abc");
+    assert_eq!("a c".escape_default(), "a c");
+    assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
+    assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
+    assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
+    assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
+    assert_eq!("ab\u{fb00}".escape_default(), "ab\\u{fb00}");
+    assert_eq!("\u{1d4ea}\r".escape_default(), "\\u{1d4ea}\\r");
 }
 
 #[test]
 fn test_total_ord() {
-    "1234".cmp("123") == Greater;
-    "123".cmp("1234") == Less;
-    "1234".cmp("1234") == Equal;
-    "12345555".cmp("123456") == Less;
-    "22".cmp("1234") == Greater;
+    assert_eq!("1234".cmp("123"), Greater);
+    assert_eq!("123".cmp("1234"), Less);
+    assert_eq!("1234".cmp("1234"), Equal);
+    assert_eq!("12345555".cmp("123456"), Less);
+    assert_eq!("22".cmp("1234"), Greater);
 }
 
 #[test]
@@ -1014,13 +997,10 @@ fn test_str_container() {
         v.iter().map(|x| x.len()).sum()
     }
 
-    let s = String::from("01234");
+    let s = "01234";
     assert_eq!(5, sum_len(&["012", "", "34"]));
-    assert_eq!(5, sum_len(&[&String::from("01"),
-                            &String::from("2"),
-                            &String::from("34"),
-                            &String::from("")]));
-    assert_eq!(5, sum_len(&[&s]));
+    assert_eq!(5, sum_len(&["01", "2", "34", ""]));
+    assert_eq!(5, sum_len(&[s]));
 }
 
 #[test]
@@ -1047,7 +1027,7 @@ fn test_pattern_deref_forward() {
 fn test_empty_match_indices() {
     let data = "aä中!";
     let vec: Vec<_> = data.match_indices("").collect();
-    assert_eq!(vec, [(0, 0), (1, 1), (3, 3), (6, 6), (7, 7)]);
+    assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
 }
 
 #[test]
@@ -1477,7 +1457,7 @@ generate_iterator_test! {
 
 generate_iterator_test! {
     double_ended_match_indices {
-        ("a1b2c3", char::is_numeric) -> [(1, 2), (3, 4), (5, 6)];
+        ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
     }
     with str::match_indices, str::rmatch_indices;
 }
index 69553bff0e17cf988729926a982ed9c64740ab4b..89df77d074fdc0f1d39a41242c848309a7c3da3c 100644 (file)
@@ -264,7 +264,7 @@ fn test_str_add() {
 
 #[test]
 fn remove() {
-    let mut s = "ศไทย中华Việt Nam; foobar".to_string();;
+    let mut s = "ศไทย中华Việt Nam; foobar".to_string();
     assert_eq!(s.remove(0), 'ศ');
     assert_eq!(s.len(), 33);
     assert_eq!(s, "ไทย中华Việt Nam; foobar");
index 1931e372aeb91c29c6bb6443094fb3ea407cec6f..5f587789bd865ae86d1abdc3b15b80c6ce95fef7 100644 (file)
@@ -475,7 +475,7 @@ fn test_drain() {
         let mut d: VecDeque<i32> = VecDeque::new();
 
         {
-            let mut iter = d.drain();
+            let mut iter = d.drain(..);
 
             assert_eq!(iter.size_hint(), (0, Some(0)));
             assert_eq!(iter.next(), None);
@@ -492,7 +492,7 @@ fn test_drain() {
             d.push_back(i);
         }
 
-        assert_eq!(d.drain().collect::<Vec<_>>(), [0, 1, 2, 3, 4]);
+        assert_eq!(d.drain(..).collect::<Vec<_>>(), [0, 1, 2, 3, 4]);
         assert!(d.is_empty());
     }
 
@@ -506,7 +506,7 @@ fn test_drain() {
             d.push_front(i);
         }
 
-        assert_eq!(d.drain().collect::<Vec<_>>(), [8,7,6,0,1,2,3,4]);
+        assert_eq!(d.drain(..).collect::<Vec<_>>(), [8,7,6,0,1,2,3,4]);
         assert!(d.is_empty());
     }
 
@@ -521,7 +521,7 @@ fn test_drain() {
         }
 
         {
-            let mut it = d.drain();
+            let mut it = d.drain(..);
             assert_eq!(it.size_hint(), (8, Some(8)));
             assert_eq!(it.next(), Some(8));
             assert_eq!(it.size_hint(), (7, Some(7)));
index 8c785b109236d2b9974ddad982fa8c8558d7f3b0..c986914440de0ae7576d91b92c878c9d038269f3 100644 (file)
@@ -35,14 +35,23 @@ use slice::{Iter, IterMut, SliceExt};
 ///
 /// This trait can be used to implement other traits on fixed-size arrays
 /// without causing much metadata bloat.
-pub trait FixedSizeArray<T> {
+///
+/// The trait is marked unsafe in order to restrict implementors to fixed-size
+/// arrays. User of this trait can assume that implementors have the exact
+/// layout in memory of a fixed size array (for example, for unsafe
+/// initialization).
+///
+/// Note that the traits AsRef and AsMut provide similar methods for types that
+/// may not be fixed-size arrays. Implementors should prefer those traits
+/// instead.
+pub unsafe trait FixedSizeArray<T> {
     /// Converts the array to immutable slice
     fn as_slice(&self) -> &[T];
     /// Converts the array to mutable slice
     fn as_mut_slice(&mut self) -> &mut [T];
 }
 
-impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
+unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
     #[inline]
     fn as_slice(&self) -> &[T] {
         self
index d37f5169af1dff7d7b8e14e60e77660a790f7e27..1dc989018ad26d11f602d8bd0e43ba2b693f2122 100644 (file)
@@ -214,7 +214,7 @@ impl<T:Copy> Cell<T> {
 
     /// Returns a reference to the underlying `UnsafeCell`.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is `unsafe` because `UnsafeCell`'s field is public.
     ///
@@ -598,7 +598,7 @@ impl<'b, T: ?Sized> Ref<'b, T> {
         }
     }
 
-    /// Make a new `Ref` for a optional component of the borrowed data, e.g. an
+    /// Make a new `Ref` for an optional component of the borrowed data, e.g. an
     /// enum variant.
     ///
     /// The `RefCell` is already immutably borrowed, so this cannot fail.
@@ -668,7 +668,7 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
         }
     }
 
-    /// Make a new `RefMut` for a optional component of the borrowed data, e.g.
+    /// Make a new `RefMut` for an optional component of the borrowed data, e.g.
     /// an enum variant.
     ///
     /// The `RefCell` is already mutably borrowed, so this cannot fail.
@@ -784,9 +784,6 @@ impl<'b, T: ?Sized> DerefMut for RefMut<'b, T> {
 ///
 /// unsafe impl<T> Sync for NotThreadSafe<T> {}
 /// ```
-///
-/// **NOTE:** `UnsafeCell<T>`'s fields are public to allow static initializers. It is not
-/// recommended to access its fields directly, `get` should be used instead.
 #[lang = "unsafe_cell"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct UnsafeCell<T: ?Sized> {
@@ -799,8 +796,7 @@ impl<T> UnsafeCell<T> {
     /// Constructs a new instance of `UnsafeCell` which will wrap the specified
     /// value.
     ///
-    /// All access to the inner value through methods is `unsafe`, and it is highly discouraged to
-    /// access the fields directly.
+    /// All access to the inner value through methods is `unsafe`.
     ///
     /// # Examples
     ///
@@ -817,7 +813,7 @@ impl<T> UnsafeCell<T> {
 
     /// Unwraps the value.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because this thread or another thread may currently be
     /// inspecting the inner value.
index dfcbfd476bc3fff7c23458c5f40dbc194920458e..21146f98360f7c7b8319080d216ca313a782b1c3 100644 (file)
@@ -91,8 +91,7 @@ pub fn from_u32(i: u32) -> Option<char> {
 /// Converts a `u32` to an `char`, not checking whether it is a valid unicode
 /// codepoint.
 #[inline]
-#[unstable(feature = "char_from_unchecked", reason = "recently added API",
-           issue = "27781")]
+#[stable(feature = "char_from_unchecked", since = "1.5.0")]
 pub unsafe fn from_u32_unchecked(i: u32) -> char {
     transmute(i)
 }
@@ -185,9 +184,7 @@ impl CharExt for char {
             '\t' => EscapeDefaultState::Backslash('t'),
             '\r' => EscapeDefaultState::Backslash('r'),
             '\n' => EscapeDefaultState::Backslash('n'),
-            '\\' => EscapeDefaultState::Backslash('\\'),
-            '\'' => EscapeDefaultState::Backslash('\''),
-            '"'  => EscapeDefaultState::Backslash('"'),
+            '\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
             '\x20' ... '\x7e' => EscapeDefaultState::Char(self),
             _ => EscapeDefaultState::Unicode(self.escape_unicode())
         };
@@ -344,6 +341,22 @@ impl Iterator for EscapeUnicode {
             EscapeUnicodeState::Done => None,
         }
     }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let mut n = 0;
+        while (self.c as usize) >> (4 * (n + 1)) != 0 {
+            n += 1;
+        }
+        let n = match self.state {
+            EscapeUnicodeState::Backslash => n + 5,
+            EscapeUnicodeState::Type => n + 4,
+            EscapeUnicodeState::LeftBrace => n + 3,
+            EscapeUnicodeState::Value(offset) => offset + 2,
+            EscapeUnicodeState::RightBrace => 1,
+            EscapeUnicodeState::Done => 0,
+        };
+        (n, Some(n))
+    }
 }
 
 /// An iterator over the characters that represent a `char`, escaped
@@ -377,7 +390,16 @@ impl Iterator for EscapeDefault {
                 Some(c)
             }
             EscapeDefaultState::Done => None,
-            EscapeDefaultState::Unicode(ref mut iter) => iter.next()
+            EscapeDefaultState::Unicode(ref mut iter) => iter.next(),
+        }
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        match self.state {
+            EscapeDefaultState::Char(_) => (1, Some(1)),
+            EscapeDefaultState::Backslash(_) => (2, Some(2)),
+            EscapeDefaultState::Unicode(ref iter) => iter.size_hint(),
+            EscapeDefaultState::Done => (0, Some(0)),
         }
     }
 }
index aea5feb4be1ff4e942892bd4a7b5e0334d5700e0..fa1f4727bc0782f046b3429026411be93fa92fdb 100644 (file)
@@ -218,7 +218,7 @@ impl PartialOrd for Ordering {
 ///
 /// The comparison must satisfy, for all `a`, `b` and `c`:
 ///
-/// - antisymmetry: if `a < b` then `!(a > b)` and vice versa; and
+/// - antisymmetry: if `a < b` then `!(a > b)`, as well as `a > b` implying `!(a < b)`; and
 /// - transitivity: `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
 ///
 /// Note that these requirements mean that the trait itself must be implemented symmetrically and
@@ -463,17 +463,33 @@ mod impls {
         }
     }
 
-    partial_ord_impl! { char usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
+    partial_ord_impl! { f32 f64 }
 
     macro_rules! ord_impl {
         ($($t:ty)*) => ($(
+            #[stable(feature = "rust1", since = "1.0.0")]
+            impl PartialOrd for $t {
+                #[inline]
+                fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
+                    Some(self.cmp(other))
+                }
+                #[inline]
+                fn lt(&self, other: &$t) -> bool { (*self) < (*other) }
+                #[inline]
+                fn le(&self, other: &$t) -> bool { (*self) <= (*other) }
+                #[inline]
+                fn ge(&self, other: &$t) -> bool { (*self) >= (*other) }
+                #[inline]
+                fn gt(&self, other: &$t) -> bool { (*self) > (*other) }
+            }
+
             #[stable(feature = "rust1", since = "1.0.0")]
             impl Ord for $t {
                 #[inline]
                 fn cmp(&self, other: &$t) -> Ordering {
-                    if *self < *other { Less }
-                    else if *self > *other { Greater }
-                    else { Equal }
+                    if *self == *other { Equal }
+                    else if *self < *other { Less }
+                    else { Greater }
                 }
             }
         )*)
index 95dab3d165ad3f99cfa4db8034afa5cc492b0d7d..3863f63265b9383314a4d6d89163675f013084b5 100644 (file)
@@ -21,9 +21,9 @@ macro_rules! __impl_slice_eq1 {
         #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
             #[inline]
-            fn eq(&self, other: &$Rhs) -> bool { &self[..] == &other[..] }
+            fn eq(&self, other: &$Rhs) -> bool { self[..] == other[..] }
             #[inline]
-            fn ne(&self, other: &$Rhs) -> bool { &self[..] != &other[..] }
+            fn ne(&self, other: &$Rhs) -> bool { self[..] != other[..] }
         }
     }
 }
@@ -39,9 +39,9 @@ macro_rules! __impl_slice_eq2 {
         #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {
             #[inline]
-            fn eq(&self, other: &$Lhs) -> bool { &self[..] == &other[..] }
+            fn eq(&self, other: &$Lhs) -> bool { self[..] == other[..] }
             #[inline]
-            fn ne(&self, other: &$Lhs) -> bool { &self[..] != &other[..] }
+            fn ne(&self, other: &$Lhs) -> bool { self[..] != other[..] }
         }
     }
 }
index 70868805299f3a910a7a5858f33a508606acb1cb..b02b2a06b75d5a3091d14ab1b59d7f974a5c7767 100644 (file)
@@ -95,7 +95,7 @@ pub trait Into<T>: Sized {
 /// assert_eq!(string, other_string);
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub trait From<T> {
+pub trait From<T>: Sized {
     /// Performs the conversion.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn from(T) -> Self;
index 0e318f204eb9d3c43871bc4ccd288c5b163e4d3d..f7fda3d04fd615a6397f9686ab4a053fc94e468c 100644 (file)
@@ -78,6 +78,8 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+use marker::Sized;
+
 /// A trait for giving a type a useful default value.
 ///
 /// A struct can derive default implementations of `Default` for basic types using
@@ -93,7 +95,7 @@
 /// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub trait Default {
+pub trait Default: Sized {
     /// Returns the "default value" for a type.
     ///
     /// Default values are often some kind of initial value, identity value, or anything else that
index 764d12dd9033435b0ddf9619731be5e73bff01a8..0d4c0bb6480086c34a71e37ed13c45458cf26e1e 100644 (file)
@@ -61,7 +61,8 @@ pub struct DebugStruct<'a, 'b: 'a> {
     has_fields: bool,
 }
 
-pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str)
+pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>,
+                                name: &str)
                                 -> DebugStruct<'a, 'b> {
     let result = fmt.write_str(name);
     DebugStruct {
@@ -84,7 +85,8 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
 
             if self.is_pretty() {
                 let mut writer = PadAdapter::new(self.fmt);
-                fmt::write(&mut writer, format_args!("{}\n{}: {:#?}", prefix, name, value))
+                fmt::write(&mut writer,
+                           format_args!("{}\n{}: {:#?}", prefix, name, value))
             } else {
                 write!(self.fmt, "{} {}: {:?}", prefix, name, value)
             }
@@ -195,10 +197,18 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> {
         self.result = self.result.and_then(|_| {
             if self.is_pretty() {
                 let mut writer = PadAdapter::new(self.fmt);
-                let prefix = if self.has_fields { "," } else { "" };
+                let prefix = if self.has_fields {
+                    ","
+                } else {
+                    ""
+                };
                 fmt::write(&mut writer, format_args!("{}\n{:#?}", prefix, entry))
             } else {
-                let prefix = if self.has_fields { ", " } else { "" };
+                let prefix = if self.has_fields {
+                    ", "
+                } else {
+                    ""
+                };
                 write!(self.fmt, "{}{:?}", prefix, entry)
             }
         });
@@ -207,7 +217,11 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> {
     }
 
     pub fn finish(&mut self) {
-        let prefix = if self.is_pretty() && self.has_fields { "\n" } else { "" };
+        let prefix = if self.is_pretty() && self.has_fields {
+            "\n"
+        } else {
+            ""
+        };
         self.result = self.result.and_then(|_| self.fmt.write_str(prefix));
     }
 
@@ -232,7 +246,7 @@ pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b
             fmt: fmt,
             result: result,
             has_fields: false,
-        }
+        },
     }
 }
 
@@ -247,7 +261,9 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> {
     /// Adds the contents of an iterator of entries to the set output.
     #[stable(feature = "debug_builders", since = "1.2.0")]
     pub fn entries<D, I>(&mut self, entries: I) -> &mut DebugSet<'a, 'b>
-            where D: fmt::Debug, I: IntoIterator<Item=D> {
+        where D: fmt::Debug,
+              I: IntoIterator<Item = D>
+    {
         for entry in entries {
             self.entry(&entry);
         }
@@ -278,7 +294,7 @@ pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a,
             fmt: fmt,
             result: result,
             has_fields: false,
-        }
+        },
     }
 }
 
@@ -293,7 +309,9 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> {
     /// Adds the contents of an iterator of entries to the list output.
     #[stable(feature = "debug_builders", since = "1.2.0")]
     pub fn entries<D, I>(&mut self, entries: I) -> &mut DebugList<'a, 'b>
-            where D: fmt::Debug, I: IntoIterator<Item=D> {
+        where D: fmt::Debug,
+              I: IntoIterator<Item = D>
+    {
         for entry in entries {
             self.entry(&entry);
         }
@@ -335,10 +353,19 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
         self.result = self.result.and_then(|_| {
             if self.is_pretty() {
                 let mut writer = PadAdapter::new(self.fmt);
-                let prefix = if self.has_fields { "," } else { "" };
-                fmt::write(&mut writer, format_args!("{}\n{:#?}: {:#?}", prefix, key, value))
+                let prefix = if self.has_fields {
+                    ","
+                } else {
+                    ""
+                };
+                fmt::write(&mut writer,
+                           format_args!("{}\n{:#?}: {:#?}", prefix, key, value))
             } else {
-                let prefix = if self.has_fields { ", " } else { "" };
+                let prefix = if self.has_fields {
+                    ", "
+                } else {
+                    ""
+                };
                 write!(self.fmt, "{}{:?}: {:?}", prefix, key, value)
             }
         });
@@ -350,7 +377,10 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
     /// Adds the contents of an iterator of entries to the map output.
     #[stable(feature = "debug_builders", since = "1.2.0")]
     pub fn entries<K, V, I>(&mut self, entries: I) -> &mut DebugMap<'a, 'b>
-            where K: fmt::Debug, V: fmt::Debug, I: IntoIterator<Item=(K, V)> {
+        where K: fmt::Debug,
+              V: fmt::Debug,
+              I: IntoIterator<Item = (K, V)>
+    {
         for (k, v) in entries {
             self.entry(&k, &v);
         }
@@ -360,7 +390,11 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> {
     /// Finishes output and returns any error encountered.
     #[stable(feature = "debug_builders", since = "1.2.0")]
     pub fn finish(&mut self) -> fmt::Result {
-        let prefix = if self.is_pretty() && self.has_fields { "\n" } else { "" };
+        let prefix = if self.is_pretty() && self.has_fields {
+            "\n"
+        } else {
+            ""
+        };
         self.result.and_then(|_| write!(self.fmt, "{}}}", prefix))
     }
 
index db7e6d3006f3f25f6bfb4a1a2fafb96edd76c089..f850cdbbd609057bb752bdbdd1bbeff1acb4ec87 100644 (file)
@@ -94,7 +94,7 @@ pub trait Write {
         self.write_str(unsafe { str::from_utf8_unchecked(&utf_8[..bytes_written]) })
     }
 
-    /// Glue for usage of the `write!` macro with implementers of this trait.
+    /// Glue for usage of the `write!` macro with implementors of this trait.
     ///
     /// This method should generally not be invoked manually, but rather through
     /// the `write!` macro itself.
@@ -298,7 +298,7 @@ impl<'a> Display for Arguments<'a> {
 ///
 /// For more information on formatters, see [the module-level documentation][module].
 ///
-/// [module]: ../index.html
+/// [module]: ../../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -393,7 +393,7 @@ pub trait Debug {
 ///
 /// For more information on formatters, see [the module-level documentation][module].
 ///
-/// [module]: ../index.html
+/// [module]: ../../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -435,7 +435,7 @@ pub trait Display {
 ///
 /// For more information on formatters, see [the module-level documentation][module].
 ///
-/// [module]: ../index.html
+/// [module]: ../../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -482,7 +482,7 @@ pub trait Octal {
 ///
 /// For more information on formatters, see [the module-level documentation][module].
 ///
-/// [module]: ../index.html
+/// [module]: ../../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -523,14 +523,14 @@ pub trait Binary {
 
 /// Format trait for the `x` character.
 ///
-/// The `LowerHex` trait should format its output as a number in hexidecimal, with `a` through `f`
+/// The `LowerHex` trait should format its output as a number in hexadecimal, with `a` through `f`
 /// in lower case.
 ///
 /// The alternate flag, `#`, adds a `0x` in front of the output.
 ///
 /// For more information on formatters, see [the module-level documentation][module].
 ///
-/// [module]: ../index.html
+/// [module]: ../../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -571,14 +571,14 @@ pub trait LowerHex {
 
 /// Format trait for the `X` character.
 ///
-/// The `UpperHex` trait should format its output as a number in hexidecimal, with `A` through `F`
+/// The `UpperHex` trait should format its output as a number in hexadecimal, with `A` through `F`
 /// in upper case.
 ///
 /// The alternate flag, `#`, adds a `0x` in front of the output.
 ///
 /// For more information on formatters, see [the module-level documentation][module].
 ///
-/// [module]: ../index.html
+/// [module]: ../../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -620,11 +620,11 @@ pub trait UpperHex {
 /// Format trait for the `p` character.
 ///
 /// The `Pointer` trait should format its output as a memory location. This is commonly presented
-/// as hexidecimal.
+/// as hexadecimal.
 ///
 /// For more information on formatters, see [the module-level documentation][module].
 ///
-/// [module]: ../index.html
+/// [module]: ../../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -668,7 +668,7 @@ pub trait Pointer {
 ///
 /// For more information on formatters, see [the module-level documentation][module].
 ///
-/// [module]: ../index.html
+/// [module]: ../../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -711,7 +711,7 @@ pub trait LowerExp {
 ///
 /// For more information on formatters, see [the module-level documentation][module].
 ///
-/// [module]: ../index.html
+/// [module]: ../../std/fmt/index.html
 ///
 /// # Examples
 ///
@@ -865,12 +865,12 @@ impl<'a> Formatter<'a> {
         let mut sign = None;
         if !is_positive {
             sign = Some('-'); width += 1;
-        } else if self.flags & (1 << (FlagV1::SignPlus as u32)) != 0 {
+        } else if self.sign_plus() {
             sign = Some('+'); width += 1;
         }
 
         let mut prefixed = false;
-        if self.flags & (1 << (FlagV1::Alternate as u32)) != 0 {
+        if self.alternate() {
             prefixed = true; width += prefix.char_len();
         }
 
@@ -900,7 +900,7 @@ impl<'a> Formatter<'a> {
             }
             // The sign and prefix goes before the padding if the fill character
             // is zero
-            Some(min) if self.flags & (1 << (FlagV1::SignAwareZeroPad as u32)) != 0 => {
+            Some(min) if self.sign_aware_zero_pad() => {
                 self.fill = '0';
                 try!(write_prefix(self));
                 self.with_padding(min - width, Alignment::Right, |f| {
@@ -1013,7 +1013,7 @@ impl<'a> Formatter<'a> {
             let mut formatted = formatted.clone();
             let mut align = self.align;
             let old_fill = self.fill;
-            if self.flags & (1 << (FlagV1::SignAwareZeroPad as u32)) != 0 {
+            if self.sign_aware_zero_pad() {
                 // a sign always goes first
                 let sign = unsafe { str::from_utf8_unchecked(formatted.sign) };
                 try!(self.buf.write_str(sign));
@@ -1098,25 +1098,40 @@ impl<'a> Formatter<'a> {
     pub fn flags(&self) -> u32 { self.flags }
 
     /// Character used as 'fill' whenever there is alignment
-    #[unstable(feature = "fmt_flags", reason = "method was just created",
-               issue = "27726")]
+    #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn fill(&self) -> char { self.fill }
 
     /// Flag indicating what form of alignment was requested
-    #[unstable(feature = "fmt_flags", reason = "method was just created",
+    #[unstable(feature = "fmt_flags_align", reason = "method was just created",
                issue = "27726")]
     pub fn align(&self) -> Alignment { self.align }
 
     /// Optionally specified integer width that the output should be
-    #[unstable(feature = "fmt_flags", reason = "method was just created",
-               issue = "27726")]
+    #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn width(&self) -> Option<usize> { self.width }
 
     /// Optionally specified precision for numeric types
-    #[unstable(feature = "fmt_flags", reason = "method was just created",
-               issue = "27726")]
+    #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn precision(&self) -> Option<usize> { self.precision }
 
+    /// Determines if the `+` flag was specified.
+    #[stable(feature = "fmt_flags", since = "1.5.0")]
+    pub fn sign_plus(&self) -> bool { self.flags & (1 << FlagV1::SignPlus as u32) != 0 }
+
+    /// Determines if the `-` flag was specified.
+    #[stable(feature = "fmt_flags", since = "1.5.0")]
+    pub fn sign_minus(&self) -> bool { self.flags & (1 << FlagV1::SignMinus as u32) != 0 }
+
+    /// Determines if the `#` flag was specified.
+    #[stable(feature = "fmt_flags", since = "1.5.0")]
+    pub fn alternate(&self) -> bool { self.flags & (1 << FlagV1::Alternate as u32) != 0 }
+
+    /// Determines if the `0` flag was specified.
+    #[stable(feature = "fmt_flags", since = "1.5.0")]
+    pub fn sign_aware_zero_pad(&self) -> bool {
+        self.flags & (1 << FlagV1::SignAwareZeroPad as u32) != 0
+    }
+
     /// Creates a `DebugStruct` builder designed to assist with creation of
     /// `fmt::Debug` implementations for structs.
     ///
@@ -1310,11 +1325,21 @@ impl Display for bool {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Debug for str {
     fn fmt(&self, f: &mut Formatter) -> Result {
-        try!(write!(f, "\""));
-        for c in self.chars().flat_map(|c| c.escape_default()) {
-            try!(f.write_char(c))
+        try!(f.write_char('"'));
+        let mut from = 0;
+        for (i, c) in self.char_indices() {
+            let esc = c.escape_default();
+            // If char needs escaping, flush backlog so far and write, else skip
+            if esc.size_hint() != (1, Some(1)) {
+                try!(f.write_str(&self[from..i]));
+                for c in esc {
+                    try!(f.write_char(c));
+                }
+                from = i + c.len_utf8();
+            }
         }
-        write!(f, "\"")
+        try!(f.write_str(&self[from..]));
+        f.write_char('"')
     }
 }
 
@@ -1328,12 +1353,11 @@ impl Display for str {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Debug for char {
     fn fmt(&self, f: &mut Formatter) -> Result {
-        use char::CharExt;
-        try!(write!(f, "'"));
+        try!(f.write_char('\''));
         for c in self.escape_default() {
             try!(f.write_char(c))
         }
-        write!(f, "'")
+        f.write_char('\'')
     }
 }
 
@@ -1361,7 +1385,7 @@ impl<T> Pointer for *const T {
         // it denotes whether to prefix with 0x. We use it to work out whether
         // or not to zero extend, and then unconditionally set it to get the
         // prefix.
-        if f.flags & 1 << (FlagV1::Alternate as u32) > 0 {
+        if f.alternate() {
             f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);
 
             if let None = f.width {
@@ -1410,7 +1434,7 @@ impl<'a, T> Pointer for &'a mut T {
 fn float_to_decimal_common<T>(fmt: &mut Formatter, num: &T, negative_zero: bool) -> Result
     where T: flt2dec::DecodableFloat
 {
-    let force_sign = fmt.flags & (1 << (FlagV1::SignPlus as u32)) != 0;
+    let force_sign = fmt.sign_plus();
     let sign = match (force_sign, negative_zero) {
         (false, false) => flt2dec::Sign::Minus,
         (false, true)  => flt2dec::Sign::MinusRaw,
@@ -1434,7 +1458,7 @@ fn float_to_decimal_common<T>(fmt: &mut Formatter, num: &T, negative_zero: bool)
 fn float_to_exponential_common<T>(fmt: &mut Formatter, num: &T, upper: bool) -> Result
     where T: flt2dec::DecodableFloat
 {
-    let force_sign = fmt.flags & (1 << (FlagV1::SignPlus as u32)) != 0;
+    let force_sign = fmt.sign_plus();
     let sign = match force_sign {
         false => flt2dec::Sign::Minus,
         true  => flt2dec::Sign::MinusPlus,
index 022fe6711bdb3c7379585cf3356eca0a20222d64..23642790a88984ffe707820183d7dcb521d6ce06 100644 (file)
@@ -48,7 +48,9 @@ trait GenericRadix {
     fn base(&self) -> u8;
 
     /// A radix-specific prefix string.
-    fn prefix(&self) -> &'static str { "" }
+    fn prefix(&self) -> &'static str {
+        ""
+    }
 
     /// Converts an integer to corresponding radix digit.
     fn digit(&self, x: u8) -> u8;
@@ -70,7 +72,10 @@ trait GenericRadix {
                 x = x / base;                  // Deaccumulate the number.
                 *byte = self.digit(n.to_u8()); // Store the digit in the buffer.
                 curr -= 1;
-                if x == zero { break };        // No more digits left to accumulate.
+                if x == zero {
+                    // No more digits left to accumulate.
+                    break
+                };
             }
         } else {
             // Do the same as above, but accounting for two's complement.
@@ -79,7 +84,10 @@ trait GenericRadix {
                 x = x / base;                  // Deaccumulate the number.
                 *byte = self.digit(n.to_u8()); // Store the digit in the buffer.
                 curr -= 1;
-                if x == zero { break };        // No more digits left to accumulate.
+                if x == zero {
+                    // No more digits left to accumulate.
+                    break
+                };
             }
         }
         let buf = unsafe { str::from_utf8_unchecked(&buf[curr..]) };
@@ -141,13 +149,17 @@ pub struct Radix {
 
 impl Radix {
     fn new(base: u8) -> Radix {
-        assert!(2 <= base && base <= 36, "the base must be in the range of 2..36: {}", base);
+        assert!(2 <= base && base <= 36,
+                "the base must be in the range of 2..36: {}",
+                base);
         Radix { base: base }
     }
 }
 
 impl GenericRadix for Radix {
-    fn base(&self) -> u8 { self.base }
+    fn base(&self) -> u8 {
+        self.base
+    }
     fn digit(&self, x: u8) -> u8 {
         match x {
             x @  0 ... 9 => b'0' + x,
index 033834dd5aaaa59dc7941eb5a82f06271782a599..f889045a3f59568b14eeca4689a0bf21c11975d1 100644 (file)
@@ -53,5 +53,5 @@ pub enum Count {
 #[derive(Copy, Clone)]
 pub enum Position {
     Next,
-    At(usize)
+    At(usize),
 }
index 2a4c909d6384c5b877ade8e2970e2a2e0d4dd245..4e038f455e1bea1bc5b17d851fbfea1f7bfdaaa1 100644 (file)
@@ -100,7 +100,9 @@ pub trait Hash {
 
     /// Feeds a slice of this type into the state provided.
     #[stable(feature = "hash_slice", since = "1.3.0")]
-    fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) where Self: Sized {
+    fn hash_slice<H: Hasher>(data: &[Self], state: &mut H)
+        where Self: Sized
+    {
         for piece in data {
             piece.hash(state);
         }
@@ -121,7 +123,9 @@ pub trait Hasher {
     /// Write a single `u8` into this hasher
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
-    fn write_u8(&mut self, i: u8) { self.write(&[i]) }
+    fn write_u8(&mut self, i: u8) {
+        self.write(&[i])
+    }
     /// Write a single `u16` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
@@ -145,8 +149,7 @@ pub trait Hasher {
     #[stable(feature = "hasher_write", since = "1.3.0")]
     fn write_usize(&mut self, i: usize) {
         let bytes = unsafe {
-            ::slice::from_raw_parts(&i as *const usize as *const u8,
-                                    mem::size_of::<usize>())
+            ::slice::from_raw_parts(&i as *const usize as *const u8, mem::size_of::<usize>())
         };
         self.write(bytes);
     }
@@ -154,23 +157,33 @@ pub trait Hasher {
     /// Write a single `i8` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
-    fn write_i8(&mut self, i: i8) { self.write_u8(i as u8) }
+    fn write_i8(&mut self, i: i8) {
+        self.write_u8(i as u8)
+    }
     /// Write a single `i16` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
-    fn write_i16(&mut self, i: i16) { self.write_u16(i as u16) }
+    fn write_i16(&mut self, i: i16) {
+        self.write_u16(i as u16)
+    }
     /// Write a single `i32` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
-    fn write_i32(&mut self, i: i32) { self.write_u32(i as u32) }
+    fn write_i32(&mut self, i: i32) {
+        self.write_u32(i as u32)
+    }
     /// Write a single `i64` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
-    fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) }
+    fn write_i64(&mut self, i: i64) {
+        self.write_u64(i as u64)
+    }
     /// Write a single `isize` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
-    fn write_isize(&mut self, i: isize) { self.write_usize(i as usize) }
+    fn write_isize(&mut self, i: isize) {
+        self.write_usize(i as usize)
+    }
 }
 
 //////////////////////////////////////////////////////////////////////////////
index 32a4f1e5bd761284cbb68576407ce80baac1a713..722d77a8a11efeccdc26f0eecfdf8eb905a1f999 100644 (file)
@@ -37,12 +37,12 @@ pub struct SipHasher {
     // and simd implementations of SipHash will use vectors
     // of v02 and v13. By placing them in this order in the struct,
     // the compiler can pick up on just a few simd optimizations by itself.
-    v0: u64,      // hash state
+    v0: u64, // hash state
     v2: u64,
     v1: u64,
     v3: u64,
     tail: u64, // unprocessed bytes le
-    ntail: usize,  // how many bytes in tail are valid
+    ntail: usize, // how many bytes in tail are valid
 }
 
 // sadly, these macro definitions can't appear later,
@@ -80,8 +80,7 @@ macro_rules! u8to64_le {
 unsafe fn load_u64_le(buf: &[u8], i: usize) -> u64 {
     debug_assert!(i + 8 <= buf.len());
     let mut data = 0u64;
-    ptr::copy_nonoverlapping(buf.get_unchecked(i),
-                             &mut data as *mut _ as *mut u8, 8);
+    ptr::copy_nonoverlapping(buf.get_unchecked(i), &mut data as *mut _ as *mut u8, 8);
     data.to_le()
 }
 
@@ -152,12 +151,12 @@ impl Hasher for SipHasher {
         if self.ntail != 0 {
             needed = 8 - self.ntail;
             if length < needed {
-                self.tail |= u8to64_le!(msg, 0, length) << 8*self.ntail;
+                self.tail |= u8to64_le!(msg, 0, length) << 8 * self.ntail;
                 self.ntail += length;
                 return
             }
 
-            let m = self.tail | u8to64_le!(msg, 0, needed) << 8*self.ntail;
+            let m = self.tail | u8to64_le!(msg, 0, needed) << 8 * self.ntail;
 
             self.v3 ^= m;
             compress!(self.v0, self.v1, self.v2, self.v3);
index ece285a831355e3610ead728e5d6193d87667c44..45b1c8a3599ca34c4b8aa88f40e389fa4cff1a4c 100644 (file)
@@ -301,7 +301,7 @@ extern "rust-intrinsic" {
     /// # Safety
     ///
     /// Beyond requiring that the program must be allowed to access both regions
-    /// of memory, it is Undefined Behaviour for source and destination to
+    /// of memory, it is Undefined Behavior for source and destination to
     /// overlap. Care must also be taken with the ownership of `src` and
     /// `dst`. This method semantically moves the values of `src` into `dst`.
     /// However it does not drop the contents of `dst`, or prevent the contents
@@ -373,20 +373,20 @@ extern "rust-intrinsic" {
     /// a size of `count` * `size_of::<T>()` and an alignment of
     /// `min_align_of::<T>()`
     ///
-    /// The volatile parameter parameter is set to `true`, so it will not be optimized out.
+    /// The volatile parameter is set to `true`, so it will not be optimized out.
     pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
                                                   count: usize);
     /// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with
     /// a size of `count` * `size_of::<T>()` and an alignment of
     /// `min_align_of::<T>()`
     ///
-    /// The volatile parameter parameter is set to `true`, so it will not be optimized out.
+    /// The volatile parameter is set to `true`, so it will not be optimized out.
     pub fn volatile_copy_memory<T>(dst: *mut T, src: *const T, count: usize);
     /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a
     /// size of `count` * `size_of::<T>()` and an alignment of
     /// `min_align_of::<T>()`.
     ///
-    /// The volatile parameter parameter is set to `true`, so it will not be optimized out.
+    /// The volatile parameter is set to `true`, so it will not be optimized out.
     pub fn volatile_set_memory<T>(dst: *mut T, val: u8, count: usize);
 
     /// Perform a volatile load from the `src` pointer.
index 97dcb2475a3cf3dfc95927d6c4cf930a8c8da582..5353fcaa3b40500767e810598a334a8b5a5367b6 100644 (file)
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Composable external iterators
+//! Composable external iteration
 //!
-//! # The `Iterator` trait
+//! If you've found yourself with a collection of some kind, and needed to
+//! perform an operation on the elements of said collection, you'll quickly run
+//! into 'iterators'. Iterators are heavily used in idiomatic Rust code, so
+//! it's worth becoming familiar with them.
 //!
-//! This module defines Rust's core iteration trait. The `Iterator` trait has
-//! one unimplemented method, `next`. All other methods are derived through
-//! default methods to perform operations such as `zip`, `chain`, `enumerate`,
-//! and `fold`.
+//! Before explaining more, let's talk about how this module is structured:
 //!
-//! The goal of this module is to unify iteration across all containers in Rust.
-//! An iterator can be considered as a state machine which is used to track
-//! which element will be yielded next.
+//! # Organization
 //!
-//! There are various extensions also defined in this module to assist with
-//! various types of iteration, such as the `DoubleEndedIterator` for iterating
-//! in reverse, the `FromIterator` trait for creating a container from an
-//! iterator, and much more.
+//! This module is largely organized by type:
 //!
-//! # Rust's `for` loop
+//! * [Traits] are the core portion: these traits define what kind of iterators
+//!   exist and what you can do with them. The methods of these traits are worth
+//!   putting some extra study time into.
+//! * [Functions] provide some helpful ways to create some basic iterators.
+//! * [Structs] are often the return types of the various methods on this
+//!   module's traits. You'll usually want to look at the method that creates
+//!   the `struct`, rather than the `struct` itself. For more detail about why,
+//!   see '[Implementing Iterator](#implementing-iterator)'.
 //!
-//! The special syntax used by rust's `for` loop is based around the
-//! `IntoIterator` trait defined in this module. `for` loops can be viewed as a
-//! syntactical expansion into a `loop`, for example, the `for` loop in this
-//! example is essentially translated to the `loop` below.
+//! [Traits]: #traits
+//! [Functions]: #functions
+//! [Structs]: #structs
+//!
+//! That's it! Let's dig into iterators.
+//!
+//! # Iterator
+//!
+//! The heart and soul of this module is the [`Iterator`] trait. The core of
+//! [`Iterator`] looks like this:
+//!
+//! ```
+//! trait Iterator {
+//!     type Item;
+//!     fn next(&mut self) -> Option<Self::Item>;
+//! }
+//! ```
+//!
+//! An iterator has a method, [`next()`], which when called, returns an
+//! [`Option`]`<Item>`. [`next()`] will return `Some(Item)` as long as there
+//! are elements, and once they've all been exhausted, will return `None` to
+//! indicate that iteration is finished. Individual iterators may choose to
+//! resume iteration, and so calling [`next()`] again may or may not eventually
+//! start returning `Some(Item)` again at some point.
+//!
+//! [`Iterator`]'s full definition includes a number of other methods as well,
+//! but they are default methods, built on top of [`next()`], and so you get
+//! them for free.
+//!
+//! Iterators are also composable, and it's common to chain them together to do
+//! more complex forms of processing. See the [Adapters](#adapters) section
+//! below for more details.
+//!
+//! [`Iterator`]: trait.Iterator.html
+//! [`next()`]: trait.Iterator.html#tymethod.next
+//! [`Option`]: ../option/enum.Option.html
+//!
+//! # The three forms of iteration
+//!
+//! There are three common methods which can create iterators from a collection:
+//!
+//! * `iter()`, which iterates over `&T`.
+//! * `iter_mut()`, which iterates over `&mut T`.
+//! * `into_iter()`, which iterates over `T`.
+//!
+//! Various things in the standard library may implement one or more of the
+//! three, where appropriate.
+//!
+//! # Implementing Iterator
+//!
+//! Creating an iterator of your own involves two steps: creating a `struct` to
+//! hold the iterator's state, and then `impl`ementing [`Iterator`] for that
+//! `struct`. This is why there are so many `struct`s in this module: there is
+//! one for each iterator and iterator adapter.
+//!
+//! Let's make an iterator named `Counter` which counts from `1` to `5`:
 //!
 //! ```
-//! let values = vec![1, 2, 3];
+//! // First, the struct:
+//!
+//! /// An iterator which counts from one to five
+//! struct Counter {
+//!     count: usize,
+//! }
+//!
+//! // we want our count to start at one, so let's add a new() method to help.
+//! // This isn't strictly necessary, but is convenient. Note that we start
+//! // `count` at zero, we'll see why in `next()`'s implementation below.
+//! impl Counter {
+//!     fn new() -> Counter {
+//!         Counter { count: 0 }
+//!     }
+//! }
+//!
+//! // Then, we implement `Iterator` for our `Counter`:
+//!
+//! impl Iterator for Counter {
+//!     // we will be counting with usize
+//!     type Item = usize;
+//!
+//!     // next() is the only required method
+//!     fn next(&mut self) -> Option<usize> {
+//!         // increment our count. This is why we started at zero.
+//!         self.count += 1;
+//!
+//!         // check to see if we've finished counting or not.
+//!         if self.count < 6 {
+//!             Some(self.count)
+//!         } else {
+//!             None
+//!         }
+//!     }
+//! }
+//!
+//! // And now we can use it!
+//!
+//! let mut counter = Counter::new();
+//!
+//! let x = counter.next().unwrap();
+//! println!("{}", x);
+//!
+//! let x = counter.next().unwrap();
+//! println!("{}", x);
+//!
+//! let x = counter.next().unwrap();
+//! println!("{}", x);
+//!
+//! let x = counter.next().unwrap();
+//! println!("{}", x);
+//!
+//! let x = counter.next().unwrap();
+//! println!("{}", x);
+//! ```
+//!
+//! This will print `1` through `5`, each on their own line.
+//!
+//! Calling `next()` this way gets repetitive. Rust has a construct which can
+//! call `next()` on your iterator, until it reaches `None`. Let's go over that
+//! next.
+//!
+//! # for Loops and IntoIterator
+//!
+//! Rust's `for` loop syntax is actually sugar for iterators. Here's a basic
+//! example of `for`:
+//!
+//! ```
+//! let values = vec![1, 2, 3, 4, 5];
 //!
 //! for x in values {
 //!     println!("{}", x);
 //! }
+//! ```
 //!
-//! // Rough translation of the iteration without a `for` iterator.
-//! # let values = vec![1, 2, 3];
-//! let mut it = values.into_iter();
-//! loop {
-//!     match it.next() {
-//!         Some(x) => println!("{}", x),
-//!         None => break,
-//!     }
+//! This will print the numbers one through five, each on their own line. But
+//! you'll notice something here: we never called anything on our vector to
+//! produce an iterator. What gives?
+//!
+//! There's a trait in the standard library for converting something into an
+//! iterator: [`IntoIterator`]. This trait has one method, [`into_iter()`],
+//! which converts the thing implementing [`IntoIterator`] into an iterator.
+//! Let's take a look at that `for` loop again, and what the compiler converts
+//! it into:
+//!
+//! [`IntoIterator`]: trait.IntoIterator.html
+//! [`into_iter()`]: trait.IntoIterator.html#tymethod.into_iter
+//!
+//! ```
+//! let values = vec![1, 2, 3, 4, 5];
+//!
+//! for x in values {
+//!     println!("{}", x);
 //! }
 //! ```
 //!
-//! Because `Iterator`s implement `IntoIterator`, this `for` loop syntax can be
-//! applied to any iterator over any type.
+//! Rust de-sugars this into:
+//!
+//! ```
+//! let values = vec![1, 2, 3, 4, 5];
+//! {
+//!     let result = match values.into_iter() {
+//!         mut iter => loop {
+//!             match iter.next() {
+//!                 Some(x) => { println!("{}", x); },
+//!                 None => break,
+//!             }
+//!         },
+//!     };
+//!     result
+//! }
+//! ```
+//!
+//! First, we call `into_iter()` on the value. Then, we match on the iterator
+//! that returns, calling [`next()`] over and over until we see a `None`. At
+//! that point, we `break` out of the loop, and we're done iterating.
+//!
+//! There's one more subtle bit here: the standard library contains an
+//! interesting implementation of [`IntoIterator`]:
+//!
+//! ```ignore
+//! impl<I: Iterator> IntoIterator for I
+//! ```
+//!
+//! In other words, all [`Iterator`]s implement [`IntoIterator`], by just
+//! returning themselves. This means two things:
+//!
+//! 1. If you're writing an [`Iterator`], you can use it with a `for` loop.
+//! 2. If you're creating a collection, implementing [`IntoIterator`] for it
+//!    will allow your collection to be used with the `for` loop.
+//!
+//! # Adapters
+//!
+//! Functions which take an [`Iterator`] and return another [`Iterator`] are
+//! often called 'iterator adapters', as they're a form of the 'adapter
+//! pattern'.
+//!
+//! Common iterator adapters include [`map()`], [`take()`], and [`collect()`].
+//! For more, see their documentation.
+//!
+//! [`map()`]: trait.Iterator.html#method.map
+//! [`take()`]: trait.Iterator.html#method.take
+//! [`collect()`]: trait.Iterator.html#method.collect
+//!
+//! # Laziness
+//!
+//! Iterators (and iterator [adapters](#adapters)) are *lazy*. This means that
+//! just creating an iterator doesn't _do_ a whole lot. Nothing really happens
+//! until you call [`next()`]. This is sometimes a source of confusion when
+//! creating an iterator solely for its side effects. For example, the [`map()`]
+//! method calls a closure on each element it iterates over:
+//!
+//! ```
+//! let v = vec![1, 2, 3, 4, 5];
+//! v.iter().map(|x| println!("{}", x));
+//! ```
+//!
+//! This will not print any values, as we only created an iterator, rather than
+//! using it. The compiler will warn us about this kind of behavior:
+//!
+//! ```text
+//! warning: unused result which must be used: iterator adaptors are lazy and
+//! do nothing unless consumed
+//! ```
+//!
+//! The idiomatic way to write a [`map()`] for its side effects is to use a
+//! `for` loop instead:
+//!
+//! ```
+//! let v = vec![1, 2, 3, 4, 5];
+//!
+//! for x in &v {
+//!     println!("{}", x);
+//! }
+//! ```
+//!
+//! [`map()`]: trait.Iterator.html#method.map
+//!
+//! The two most common ways to evaluate an iterator are to use a `for` loop
+//! like this, or using the [`collect()`] adapter to produce a new collection.
+//!
+//! [`collect()`]: trait.Iterator.html#method.collect
+//!
+//! # Infinity
+//!
+//! Iterators do not have to be finite. As an example, an open-ended range is
+//! an infinite iterator:
+//!
+//! ```
+//! let numbers = 0..;
+//! ```
+//!
+//! It is common to use the [`take()`] iterator adapter to turn an infinite
+//! iterator into a finite one:
+//!
+//! ```
+//! let numbers = 0..;
+//! let five_numbers = numbers.take(5);
+//!
+//! for number in five_numbers {
+//!     println!("{}", number);
+//! }
+//! ```
+//!
+//! This will print the numbers `0` through `4`, each on their own line.
+//!
+//! [`take()`]: trait.Iterator.html#method.take
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -165,7 +407,7 @@ pub trait Iterator {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn nth(&mut self, mut n: usize) -> Option<Self::Item> where Self: Sized {
-        for x in self.by_ref() {
+        for x in self {
             if n == 0 { return Some(x) }
             n -= 1;
         }
@@ -637,7 +879,7 @@ pub trait Iterator {
     fn all<F>(&mut self, mut f: F) -> bool where
         Self: Sized, F: FnMut(Self::Item) -> bool
     {
-        for x in self.by_ref() {
+        for x in self {
             if !f(x) {
                 return false;
             }
@@ -664,7 +906,7 @@ pub trait Iterator {
         Self: Sized,
         F: FnMut(Self::Item) -> bool
     {
-        for x in self.by_ref() {
+        for x in self {
             if f(x) {
                 return true;
             }
@@ -689,7 +931,7 @@ pub trait Iterator {
         Self: Sized,
         P: FnMut(&Self::Item) -> bool,
     {
-        for x in self.by_ref() {
+        for x in self {
             if predicate(&x) { return Some(x) }
         }
         None
@@ -725,7 +967,7 @@ pub trait Iterator {
         P: FnMut(Self::Item) -> bool,
     {
         // `enumerate` might overflow.
-        for (i, x) in self.by_ref().enumerate() {
+        for (i, x) in self.enumerate() {
             if predicate(x) {
                 return Some(i);
             }
@@ -935,7 +1177,7 @@ pub trait Iterator {
 
     /// Creates an iterator that clones the elements it yields.
     ///
-    /// This is useful for converting an Iterator<&T> to an Iterator<T>,
+    /// This is useful for converting an `Iterator<&T>` to an`Iterator<T>`,
     /// so it's a more convenient form of `map(|&x| x)`.
     ///
     /// # Examples
@@ -1015,7 +1257,7 @@ pub trait Iterator {
 
     /// Lexicographically compares the elements of this `Iterator` with those
     /// of another.
-    #[unstable(feature = "iter_order", reason = "needs review and revision", issue = "27737")]
+    #[stable(feature = "iter_order", since = "1.5.0")]
     fn cmp<I>(mut self, other: I) -> Ordering where
         I: IntoIterator<Item = Self::Item>,
         Self::Item: Ord,
@@ -1038,7 +1280,7 @@ pub trait Iterator {
 
     /// Lexicographically compares the elements of this `Iterator` with those
     /// of another.
-    #[unstable(feature = "iter_order", reason = "needs review and revision", issue = "27737")]
+    #[stable(feature = "iter_order", since = "1.5.0")]
     fn partial_cmp<I>(mut self, other: I) -> Option<Ordering> where
         I: IntoIterator,
         Self::Item: PartialOrd<I::Item>,
@@ -1061,7 +1303,7 @@ pub trait Iterator {
 
     /// Determines if the elements of this `Iterator` are equal to those of
     /// another.
-    #[unstable(feature = "iter_order", reason = "needs review and revision", issue = "27737")]
+    #[stable(feature = "iter_order", since = "1.5.0")]
     fn eq<I>(mut self, other: I) -> bool where
         I: IntoIterator,
         Self::Item: PartialEq<I::Item>,
@@ -1080,7 +1322,7 @@ pub trait Iterator {
 
     /// Determines if the elements of this `Iterator` are unequal to those of
     /// another.
-    #[unstable(feature = "iter_order", reason = "needs review and revision", issue = "27737")]
+    #[stable(feature = "iter_order", since = "1.5.0")]
     fn ne<I>(mut self, other: I) -> bool where
         I: IntoIterator,
         Self::Item: PartialEq<I::Item>,
@@ -1099,7 +1341,7 @@ pub trait Iterator {
 
     /// Determines if the elements of this `Iterator` are lexicographically
     /// less than those of another.
-    #[unstable(feature = "iter_order", reason = "needs review and revision", issue = "27737")]
+    #[stable(feature = "iter_order", since = "1.5.0")]
     fn lt<I>(mut self, other: I) -> bool where
         I: IntoIterator,
         Self::Item: PartialOrd<I::Item>,
@@ -1126,7 +1368,7 @@ pub trait Iterator {
 
     /// Determines if the elements of this `Iterator` are lexicographically
     /// less or equal to those of another.
-    #[unstable(feature = "iter_order", reason = "needs review and revision", issue = "27737")]
+    #[stable(feature = "iter_order", since = "1.5.0")]
     fn le<I>(mut self, other: I) -> bool where
         I: IntoIterator,
         Self::Item: PartialOrd<I::Item>,
@@ -1153,7 +1395,7 @@ pub trait Iterator {
 
     /// Determines if the elements of this `Iterator` are lexicographically
     /// greater than those of another.
-    #[unstable(feature = "iter_order", reason = "needs review and revision", issue = "27737")]
+    #[stable(feature = "iter_order", since = "1.5.0")]
     fn gt<I>(mut self, other: I) -> bool where
         I: IntoIterator,
         Self::Item: PartialOrd<I::Item>,
@@ -1180,7 +1422,7 @@ pub trait Iterator {
 
     /// Determines if the elements of this `Iterator` are lexicographically
     /// greater than or equal to those of another.
-    #[unstable(feature = "iter_order", reason = "needs review and revision", issue = "27737")]
+    #[stable(feature = "iter_order", since = "1.5.0")]
     fn ge<I>(mut self, other: I) -> bool where
         I: IntoIterator,
         Self::Item: PartialOrd<I::Item>,
@@ -1211,7 +1453,7 @@ pub trait Iterator {
 ///
 /// This is an idiosyncratic helper to try to factor out the
 /// commonalities of {max,min}{,_by}. In particular, this avoids
-/// having to implement optimisations several times.
+/// having to implement optimizations several times.
 #[inline]
 fn select_fold1<I,B, FProj, FCmp>(mut it: I,
                                   mut f_proj: FProj,
@@ -1244,11 +1486,11 @@ impl<'a, I: Iterator + ?Sized> Iterator for &'a mut I {
     fn size_hint(&self) -> (usize, Option<usize>) { (**self).size_hint() }
 }
 
-/// Conversion from an `Iterator`
+/// Conversion from an `Iterator`.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented="a collection of type `{Self}` cannot be \
                           built from an iterator over elements of type `{A}`"]
-pub trait FromIterator<A> {
+pub trait FromIterator<A>: Sized {
     /// Builds a container with elements from something iterable.
     ///
     /// # Examples
@@ -1276,21 +1518,90 @@ pub trait FromIterator<A> {
     fn from_iter<T: IntoIterator<Item=A>>(iterator: T) -> Self;
 }
 
-/// Conversion into an `Iterator`
+/// Conversion into an `Iterator`.
+///
+/// By implementing `IntoIterator` for a type, you define how it will be
+/// converted to an iterator. This is common for types which describe a
+/// collection of some kind.
+///
+/// One benefit of implementing `IntoIterator` is that your type will [work
+/// with Rust's `for` loop syntax](index.html#for-loops-and-intoiterator).
 ///
-/// Implementing this trait allows you to use your type with Rust's `for` loop. See
-/// the [module level documentation](index.html) for more details.
+/// # Examples
+///
+/// Vectors implement `IntoIterator`:
+///
+/// ```
+/// let v = vec![1, 2, 3];
+///
+/// let mut iter = v.into_iter();
+///
+/// let n = iter.next();
+/// assert_eq!(Some(1), n);
+///
+/// let n = iter.next();
+/// assert_eq!(Some(2), n);
+///
+/// let n = iter.next();
+/// assert_eq!(Some(3), n);
+///
+/// let n = iter.next();
+/// assert_eq!(None, n);
+/// ```
+///
+/// Implementing `IntoIterator` for your type:
+///
+/// ```
+/// // A sample collection, that's just a wrapper over Vec<T>
+/// #[derive(Debug)]
+/// struct MyCollection(Vec<i32>);
+///
+/// // Let's give it some methods so we can create one and add things
+/// // to it.
+/// impl MyCollection {
+///     fn new() -> MyCollection {
+///         MyCollection(Vec::new())
+///     }
+///
+///     fn add(&mut self, elem: i32) {
+///         self.0.push(elem);
+///     }
+/// }
+///
+/// // and we'll implement IntoIterator
+/// impl IntoIterator for MyCollection {
+///     type Item = i32;
+///     type IntoIter = ::std::vec::IntoIter<i32>;
+///
+///     fn into_iter(self) -> Self::IntoIter {
+///         self.0.into_iter()
+///     }
+/// }
+///
+/// // Now we can make a new collection...
+/// let mut c = MyCollection::new();
+///
+/// // ... add some stuff to it ...
+/// c.add(0);
+/// c.add(1);
+/// c.add(2);
+///
+/// // ... and then turn it into an Iterator:
+/// for (i, n) in c.into_iter().enumerate() {
+///     assert_eq!(i as i32, n);
+/// }
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait IntoIterator {
-    /// The type of the elements being iterated
+    /// The type of the elements being iterated over.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Item;
 
-    /// A container for iterating over elements of type `Item`
+    /// Which kind of iterator are we turning this into?
     #[stable(feature = "rust1", since = "1.0.0")]
     type IntoIter: Iterator<Item=Self::Item>;
 
-    /// Consumes `Self` and returns an iterator over it
+    /// Consumes `Self` and returns an iterator over it.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn into_iter(self) -> Self::IntoIter;
 }
@@ -1305,23 +1616,164 @@ impl<I: Iterator> IntoIterator for I {
     }
 }
 
-/// A type growable from an `Iterator` implementation
+/// Extend a collection with the contents of an iterator.
+///
+/// Iterators produce a series of values, and collections can also be thought
+/// of as a series of values. The `Extend` trait bridges this gap, allowing you
+/// to extend a collection by including the contents of that iterator.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// // You can extend a String with some chars:
+/// let mut message = String::from("The first three letters are: ");
+///
+/// message.extend(&['a', 'b', 'c']);
+///
+/// assert_eq!("abc", &message[29..32]);
+/// ```
+///
+/// Implementing `Extend`:
+///
+/// ```
+/// // A sample collection, that's just a wrapper over Vec<T>
+/// #[derive(Debug)]
+/// struct MyCollection(Vec<i32>);
+///
+/// // Let's give it some methods so we can create one and add things
+/// // to it.
+/// impl MyCollection {
+///     fn new() -> MyCollection {
+///         MyCollection(Vec::new())
+///     }
+///
+///     fn add(&mut self, elem: i32) {
+///         self.0.push(elem);
+///     }
+/// }
+///
+/// // since MyCollection has a list of i32s, we implement Extend for i32
+/// impl Extend<i32> for MyCollection {
+///
+///     // This is a bit simpler with the concrete type signature: we can call
+///     // extend on anything which can be turned into an Iterator which gives
+///     // us i32s. Because we need i32s to put into MyCollection.
+///     fn extend<T: IntoIterator<Item=i32>>(&mut self, iterable: T) {
+///
+///         // The implementation is very straightforward: loop through the
+///         // iterator, and add() each element to ourselves.
+///         for elem in iterable {
+///             self.add(elem);
+///         }
+///     }
+/// }
+///
+/// let mut c = MyCollection::new();
+///
+/// c.add(5);
+/// c.add(6);
+/// c.add(7);
+///
+/// // let's extend our collection with three more numbers
+/// c.extend(vec![1, 2, 3]);
+///
+/// // we've added these elements onto the end
+/// assert_eq!("MyCollection([5, 6, 7, 1, 2, 3])", format!("{:?}", c));
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Extend<A> {
-    /// Extends a container with the elements yielded by an arbitrary iterator
+    /// Extends a collection with the contents of an iterator.
+    ///
+    /// As this is the only method for this trait, the [trait-level] docs
+    /// contain more details.
+    ///
+    /// [trait-level]: trait.Extend.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// // You can extend a String with some chars:
+    /// let mut message = String::from("The first three letters are: ");
+    ///
+    /// message.extend(['a', 'b', 'c'].iter());
+    ///
+    /// assert_eq!("abc", &message[29..32]);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn extend<T: IntoIterator<Item=A>>(&mut self, iterable: T);
 }
 
-/// A range iterator able to yield elements from both ends
+/// An iterator able to yield elements from both ends.
+///
+/// Something that implements `DoubleEndedIterator` has one extra capability
+/// over something that implements [`Iterator`]: the ability to also take
+/// `Item`s from the back, as well as the front.
+///
+/// It is important to note that both back and forth work on the same range,
+/// and do not cross: iteration is over when they meet in the middle.
+///
+/// [`Iterator`]: trait.Iterator.html
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// let numbers = vec![1, 2, 3];
+///
+/// let mut iter = numbers.iter();
+///
+/// let n = iter.next();
+/// assert_eq!(Some(&1), n);
+///
+/// let n = iter.next_back();
+/// assert_eq!(Some(&3), n);
 ///
-/// A `DoubleEndedIterator` can be thought of as a deque in that `next()` and
-/// `next_back()` exhaust elements from the *same* range, and do not work
-/// independently of each other.
+/// let n = iter.next_back();
+/// assert_eq!(Some(&2), n);
+///
+/// let n = iter.next();
+/// assert_eq!(None, n);
+///
+/// let n = iter.next_back();
+/// assert_eq!(None, n);
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait DoubleEndedIterator: Iterator {
-    /// Yields an element from the end of the range, returning `None` if the
-    /// range is empty.
+    /// An iterator able to yield elements from both ends.
+    ///
+    /// As this is the only method for this trait, the [trait-level] docs
+    /// contain more details.
+    ///
+    /// [trait-level]: trait.DoubleEndedIterator.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let numbers = vec![1, 2, 3];
+    ///
+    /// let mut iter = numbers.iter();
+    ///
+    /// let n = iter.next();
+    /// assert_eq!(Some(&1), n);
+    ///
+    /// let n = iter.next_back();
+    /// assert_eq!(Some(&3), n);
+    ///
+    /// let n = iter.next_back();
+    /// assert_eq!(Some(&2), n);
+    ///
+    /// let n = iter.next();
+    /// assert_eq!(None, n);
+    ///
+    /// let n = iter.next_back();
+    /// assert_eq!(None, n);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn next_back(&mut self) -> Option<Self::Item>;
 }
@@ -1331,18 +1783,98 @@ impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I {
     fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() }
 }
 
-/// An iterator that knows its exact length
+/// An iterator that knows its exact length.
+///
+/// Many [`Iterator`]s don't know how many times they will iterate, but some do.
+/// If an iterator knows how many times it can iterate, providing access to
+/// that information can be useful. For example, if you want to iterate
+/// backwards, a good start is to know where the end is.
 ///
-/// This trait is a helper for iterators like the vector iterator, so that
-/// it can support double-ended enumeration.
+/// When implementing an `ExactSizeIterator`, You must also implement
+/// [`Iterator`]. When doing so, the implementation of [`size_hint()`] *must*
+/// return the exact size of the iterator.
 ///
-/// `Iterator::size_hint` *must* return the exact size of the iterator.
-/// Note that the size must fit in `usize`.
+/// [`Iterator`]: trait.Iterator.html
+/// [`size_hint()`]: trait.Iterator.html#method.size_hint
+///
+/// The [`len()`] method has a default implementation, so you usually shouldn't
+/// implement it. However, you may be able to provide a more performant
+/// implementation than the default, so overriding it in this case makes sense.
+///
+/// [`len()`]: #method.len
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// // a finite range knows exactly how many times it will iterate
+/// let five = (0..5);
+///
+/// assert_eq!(5, five.len());
+/// ```
+///
+/// In the [module level docs][moddocs], we implemented an [`Iterator`],
+/// `Counter`. Let's implement `ExactSizeIterator` for it as well:
+///
+/// [moddocs]: index.html
+///
+/// ```
+/// # struct Counter {
+/// #     count: usize,
+/// # }
+/// # impl Counter {
+/// #     fn new() -> Counter {
+/// #         Counter { count: 0 }
+/// #     }
+/// # }
+/// # impl Iterator for Counter {
+/// #     type Item = usize;
+/// #     fn next(&mut self) -> Option<usize> {
+/// #         self.count += 1;
+/// #         if self.count < 6 {
+/// #             Some(self.count)
+/// #         } else {
+/// #             None
+/// #         }
+/// #     }
+/// # }
+/// impl ExactSizeIterator for Counter {
+///     // We already have the number of iterations, so we can use it directly.
+///     fn len(&self) -> usize {
+///         self.count
+///     }
+/// }
+///
+/// // And now we can use it!
+///
+/// let counter = Counter::new();
+///
+/// assert_eq!(0, counter.len());
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ExactSizeIterator: Iterator {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    /// Returns the exact length of the iterator.
+    /// Returns the exact number of times the iterator will iterate.
+    ///
+    /// This method has a default implementation, so you usually should not
+    /// implement it directly. However, if you can provide a more efficient
+    /// implementation, you can do so. See the [trait-level] docs for an
+    /// example.
+    ///
+    /// [trait-level]: trait.ExactSizeIterator.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// // a finite range knows exactly how many times it will iterate
+    /// let five = (0..5);
+    ///
+    /// assert_eq!(5, five.len());
+    /// ```
     fn len(&self) -> usize {
         let (lower, upper) = self.size_hint();
         // Note: This assertion is overly defensive, but it checks the invariant
@@ -1376,7 +1908,13 @@ impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F> where
 impl<A, B> ExactSizeIterator for Zip<A, B>
     where A: ExactSizeIterator, B: ExactSizeIterator {}
 
-/// An double-ended iterator with the direction inverted
+/// An double-ended iterator with the direction inverted.
+///
+/// This `struct` is created by the [`rev()`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`rev()`]: trait.Iterator.html#method.rev
+/// [`Iterator`]: trait.Iterator.html
 #[derive(Clone)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1400,7 +1938,13 @@ impl<I> DoubleEndedIterator for Rev<I> where I: DoubleEndedIterator {
     fn next_back(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next() }
 }
 
-/// An iterator that clones the elements of an underlying iterator
+/// An iterator that clones the elements of an underlying iterator.
+///
+/// This `struct` is created by the [`cloned()`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`cloned()`]: trait.Iterator.html#method.cloned
+/// [`Iterator`]: trait.Iterator.html
 #[stable(feature = "iter_cloned", since = "1.1.0")]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[derive(Clone)]
@@ -1437,7 +1981,13 @@ impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I>
     where I: ExactSizeIterator<Item=&'a T>, T: Clone
 {}
 
-/// An iterator that repeats endlessly
+/// An iterator that repeats endlessly.
+///
+/// This `struct` is created by the [`cycle()`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`cycle()`]: trait.Iterator.html#method.cycle
+/// [`Iterator`]: trait.Iterator.html
 #[derive(Clone)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1469,7 +2019,13 @@ impl<I> Iterator for Cycle<I> where I: Clone + Iterator {
     }
 }
 
-/// An iterator that strings two iterators together
+/// An iterator that strings two iterators together.
+///
+/// This `struct` is created by the [`chain()`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`chain()`]: trait.Iterator.html#method.chain
+/// [`Iterator`]: trait.Iterator.html
 #[derive(Clone)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1559,7 +2115,12 @@ impl<A, B> Iterator for Chain<A, B> where
     #[inline]
     fn last(self) -> Option<A::Item> {
         match self.state {
-            ChainState::Both => self.b.last().or(self.a.last()),
+            ChainState::Both => {
+                // Must exhaust a before b.
+                let a_last = self.a.last();
+                let b_last = self.b.last();
+                b_last.or(a_last)
+            },
             ChainState::Front => self.a.last(),
             ChainState::Back => self.b.last()
         }
@@ -1602,7 +2163,13 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where
     }
 }
 
-/// An iterator that iterates two other iterators simultaneously
+/// An iterator that iterates two other iterators simultaneously.
+///
+/// This `struct` is created by the [`zip()`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`zip()`]: trait.Iterator.html#method.zip
+/// [`Iterator`]: trait.Iterator.html
 #[derive(Clone)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1668,7 +2235,13 @@ impl<A, B> DoubleEndedIterator for Zip<A, B> where
     }
 }
 
-/// An iterator that maps the values of `iter` with `f`
+/// An iterator that maps the values of `iter` with `f`.
+///
+/// This `struct` is created by the [`map()`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`map()`]: trait.Iterator.html#method.map
+/// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone)]
@@ -1702,7 +2275,13 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F> where
     }
 }
 
-/// An iterator that filters the elements of `iter` with `predicate`
+/// An iterator that filters the elements of `iter` with `predicate`.
+///
+/// This `struct` is created by the [`filter()`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`filter()`]: trait.Iterator.html#method.filter
+/// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone)]
@@ -1747,7 +2326,13 @@ impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P>
     }
 }
 
-/// An iterator that uses `f` to both filter and map elements from `iter`
+/// An iterator that uses `f` to both filter and map elements from `iter`.
+///
+/// This `struct` is created by the [`filter_map()`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`filter_map()`]: trait.Iterator.html#method.filter_map
+/// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone)]
@@ -1794,7 +2379,13 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F>
     }
 }
 
-/// An iterator that yields the current count and the element during iteration
+/// An iterator that yields the current count and the element during iteration.
+///
+/// This `struct` is created by the [`enumerate()`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`enumerate()`]: trait.Iterator.html#method.enumerate
+/// [`Iterator`]: trait.Iterator.html
 #[derive(Clone)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1861,7 +2452,15 @@ impl<I> DoubleEndedIterator for Enumerate<I> where
     }
 }
 
-/// An iterator with a `peek()` that returns an optional reference to the next element.
+/// An iterator with a `peek()` that returns an optional reference to the next
+/// element.
+///
+/// This `struct` is created by the [`peekable()`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`peekable()`]: trait.Iterator.html#method.peekable
+/// [`Iterator`]: trait.Iterator.html
+#[derive(Clone)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Peekable<I: Iterator> {
@@ -1869,15 +2468,6 @@ pub struct Peekable<I: Iterator> {
     peeked: Option<I::Item>,
 }
 
-impl<I: Iterator + Clone> Clone for Peekable<I> where I::Item: Clone {
-    fn clone(&self) -> Peekable<I> {
-        Peekable {
-            iter: self.iter.clone(),
-            peeked: self.peeked.clone(),
-        }
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<I: Iterator> Iterator for Peekable<I> {
     type Item = I::Item;
@@ -1951,7 +2541,13 @@ impl<I: Iterator> Peekable<I> {
     }
 }
 
-/// An iterator that rejects elements while `predicate` is true
+/// An iterator that rejects elements while `predicate` is true.
+///
+/// This `struct` is created by the [`skip_while()`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`skip_while()`]: trait.Iterator.html#method.skip_while
+/// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone)]
@@ -1985,7 +2581,13 @@ impl<I: Iterator, P> Iterator for SkipWhile<I, P>
     }
 }
 
-/// An iterator that only accepts elements while `predicate` is true
+/// An iterator that only accepts elements while `predicate` is true.
+///
+/// This `struct` is created by the [`take_while()`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`take_while()`]: trait.Iterator.html#method.take_while
+/// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone)]
@@ -2025,6 +2627,12 @@ impl<I: Iterator, P> Iterator for TakeWhile<I, P>
 }
 
 /// An iterator that skips over `n` elements of `iter`.
+///
+/// This `struct` is created by the [`skip()`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`skip()`]: trait.Iterator.html#method.skip
+/// [`Iterator`]: trait.Iterator.html
 #[derive(Clone)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2099,6 +2707,12 @@ impl<I> Iterator for Skip<I> where I: Iterator {
 impl<I> ExactSizeIterator for Skip<I> where I: ExactSizeIterator {}
 
 /// An iterator that only iterates over the first `n` iterations of `iter`.
+///
+/// This `struct` is created by the [`take()`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`take()`]: trait.Iterator.html#method.take
+/// [`Iterator`]: trait.Iterator.html
 #[derive(Clone)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2154,7 +2768,13 @@ impl<I> Iterator for Take<I> where I: Iterator{
 impl<I> ExactSizeIterator for Take<I> where I: ExactSizeIterator {}
 
 
-/// An iterator to maintain state while iterating another iterator
+/// An iterator to maintain state while iterating another iterator.
+///
+/// This `struct` is created by the [`scan()`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`scan()`]: trait.Iterator.html#method.scan
+/// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone)]
@@ -2183,9 +2803,14 @@ impl<B, I, St, F> Iterator for Scan<I, St, F> where
     }
 }
 
-/// An iterator that maps each element to an iterator,
-/// and yields the elements of the produced iterators
+/// An iterator that maps each element to an iterator, and yields the elements
+/// of the produced iterators.
+///
+/// This `struct` is created by the [`flat_map()`] method on [`Iterator`]. See its
+/// documentation for more.
 ///
+/// [`flat_map()`]: trait.Iterator.html#method.flat_map
+/// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone)]
@@ -2253,6 +2878,12 @@ impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F> wher
 
 /// An iterator that yields `None` forever after the underlying iterator
 /// yields `None` once.
+///
+/// This `struct` is created by the [`fuse()`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`fuse()`]: trait.Iterator.html#method.fuse
+/// [`Iterator`]: trait.Iterator.html
 #[derive(Clone)]
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2332,8 +2963,14 @@ impl<I> DoubleEndedIterator for Fuse<I> where I: DoubleEndedIterator {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<I> ExactSizeIterator for Fuse<I> where I: ExactSizeIterator {}
 
-/// An iterator that calls a function with a reference to each
-/// element before yielding it.
+/// An iterator that calls a function with a reference to each element before
+/// yielding it.
+///
+/// This `struct` is created by the [`inspect()`] method on [`Iterator`]. See its
+/// documentation for more.
+///
+/// [`inspect()`]: trait.Iterator.html#method.inspect
+/// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone)]
@@ -2587,6 +3224,8 @@ impl<A> Iterator for StepBy<A, RangeFrom<A>> where
 #[unstable(feature = "range_inclusive",
            reason = "likely to be replaced by range notation and adapters",
            issue = "27777")]
+#[deprecated(since = "1.5.0", reason = "replaced with ... syntax")]
+#[allow(deprecated)]
 pub struct RangeInclusive<A> {
     range: ops::Range<A>,
     done: bool,
@@ -2597,6 +3236,8 @@ pub struct RangeInclusive<A> {
 #[unstable(feature = "range_inclusive",
            reason = "likely to be replaced by range notation and adapters",
            issue = "27777")]
+#[deprecated(since = "1.5.0", reason = "replaced with ... syntax")]
+#[allow(deprecated)]
 pub fn range_inclusive<A>(start: A, stop: A) -> RangeInclusive<A>
     where A: Step + One + Clone
 {
@@ -2609,6 +3250,8 @@ pub fn range_inclusive<A>(start: A, stop: A) -> RangeInclusive<A>
 #[unstable(feature = "range_inclusive",
            reason = "likely to be replaced by range notation and adapters",
            issue = "27777")]
+#[deprecated(since = "1.5.0", reason = "replaced with ... syntax")]
+#[allow(deprecated)]
 impl<A> Iterator for RangeInclusive<A> where
     A: PartialEq + Step + One + Clone,
     for<'a> &'a A: Add<&'a A, Output = A>
@@ -2643,6 +3286,8 @@ impl<A> Iterator for RangeInclusive<A> where
 #[unstable(feature = "range_inclusive",
            reason = "likely to be replaced by range notation and adapters",
            issue = "27777")]
+#[deprecated(since = "1.5.0", reason = "replaced with ... syntax")]
+#[allow(deprecated)]
 impl<A> DoubleEndedIterator for RangeInclusive<A> where
     A: PartialEq + Step + One + Clone,
     for<'a> &'a A: Add<&'a A, Output = A>,
@@ -2767,7 +3412,11 @@ impl<A: Step + One> Iterator for ops::RangeFrom<A> where
     }
 }
 
-/// An iterator that repeats an element endlessly
+/// An iterator that repeats an element endlessly.
+///
+/// This `struct` is created by the [`repeat()`] function. See its documentation for more.
+///
+/// [`repeat()`]: fn.repeat.html
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Repeat<A> {
@@ -2790,7 +3439,52 @@ impl<A: Clone> DoubleEndedIterator for Repeat<A> {
     fn next_back(&mut self) -> Option<A> { Some(self.element.clone()) }
 }
 
-/// Creates a new iterator that endlessly repeats the element `elt`.
+/// Creates a new iterator that endlessly repeats a single element.
+///
+/// The `repeat()` function repeats a single value over and over and over and
+/// over and over and 🔁.
+///
+/// Infinite iterators like `repeat()` are often used with adapters like
+/// [`take()`], in order to make them finite.
+///
+/// [`take()`]: trait.Iterator.html#method.take
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::iter;
+///
+/// // the number four 4ever:
+/// let mut fours = iter::repeat(4);
+///
+/// assert_eq!(Some(4), fours.next());
+/// assert_eq!(Some(4), fours.next());
+/// assert_eq!(Some(4), fours.next());
+/// assert_eq!(Some(4), fours.next());
+/// assert_eq!(Some(4), fours.next());
+///
+/// // yup, still four
+/// assert_eq!(Some(4), fours.next());
+/// ```
+///
+/// Going finite with [`take()`]:
+///
+/// ```
+/// use std::iter;
+///
+/// // that last example was too many fours. Let's only have four fours.
+/// let mut four_fours = iter::repeat(4).take(4);
+///
+/// assert_eq!(Some(4), four_fours.next());
+/// assert_eq!(Some(4), four_fours.next());
+/// assert_eq!(Some(4), four_fours.next());
+/// assert_eq!(Some(4), four_fours.next());
+///
+/// // ... and now we're done
+/// assert_eq!(None, four_fours.next());
+/// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
@@ -2798,6 +3492,10 @@ pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
 }
 
 /// An iterator that yields nothing.
+///
+/// This `struct` is created by the [`empty()`] function. See its documentation for more.
+///
+/// [`empty()`]: fn.empty.html
 #[stable(feature = "iter_empty", since = "1.2.0")]
 pub struct Empty<T>(marker::PhantomData<T>);
 
@@ -2847,12 +3545,29 @@ impl<T> Default for Empty<T> {
 }
 
 /// Creates an iterator that yields nothing.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::iter;
+///
+/// // this could have been an iterator over i32, but alas, it's just not.
+/// let mut nope = iter::empty::<i32>();
+///
+/// assert_eq!(None, nope.next());
+/// ```
 #[stable(feature = "iter_empty", since = "1.2.0")]
 pub fn empty<T>() -> Empty<T> {
     Empty(marker::PhantomData)
 }
 
 /// An iterator that yields an element exactly once.
+///
+/// This `struct` is created by the [`once()`] function. See its documentation for more.
+///
+/// [`once()`]: fn.once.html
 #[derive(Clone)]
 #[stable(feature = "iter_once", since = "1.2.0")]
 pub struct Once<T> {
@@ -2887,6 +3602,56 @@ impl<T> ExactSizeIterator for Once<T> {
 }
 
 /// Creates an iterator that yields an element exactly once.
+///
+/// This is commonly used to adapt a single value into a [`chain()`] of other
+/// kinds of iteration. Maybe you have an iterator that covers almost
+/// everything, but you need an extra special case. Maybe you have a function
+/// which works on iterators, but you only need to process one value.
+///
+/// [`chain()`]: trait.Iterator.html#method.chain
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::iter;
+///
+/// // one is the loneliest number
+/// let mut one = iter::once(1);
+///
+/// assert_eq!(Some(1), one.next());
+///
+/// // just one, that's all we get
+/// assert_eq!(None, one.next());
+/// ```
+///
+/// Chaining together with another iterator. Let's say that we want to iterate
+/// over each file of the `.foo` directory, but also a configuration file,
+/// `.foorc`:
+///
+/// ```no_run
+/// use std::iter;
+/// use std::fs;
+/// use std::path::PathBuf;
+///
+/// let dirs = fs::read_dir(".foo").unwrap();
+///
+/// // we need to convert from an iterator of DirEntry-s to an iterator of
+/// // PathBufs, so we use map
+/// let dirs = dirs.map(|file| file.unwrap().path());
+///
+/// // now, our iterator just for our config file
+/// let config = iter::once(PathBuf::from(".foorc"));
+///
+/// // chain the two iterators together into one big iterator
+/// let files = dirs.chain(config);
+///
+/// // this will give us all of the files in .foo as well as .foorc
+/// for f in files {
+///     println!("{:?}", f);
+/// }
+/// ```
 #[stable(feature = "iter_once", since = "1.2.0")]
 pub fn once<T>(value: T) -> Once<T> {
     Once { inner: Some(value).into_iter() }
@@ -2900,7 +3665,7 @@ pub fn once<T>(value: T) -> Once<T> {
 /// If two sequences are equal up until the point where one ends,
 /// the shorter sequence compares less.
 #[deprecated(since = "1.4.0", reason = "use the equivalent methods on `Iterator` instead")]
-#[unstable(feature = "iter_order", reason = "needs review and revision",
+#[unstable(feature = "iter_order_deprecated", reason = "needs review and revision",
            issue = "27737")]
 pub mod order {
     use cmp;
index 25ca33a3d5011c0b49f510667311ad5a7b871487..bb112327abf4b02f0075411958ca63a9af2c911b 100644 (file)
@@ -168,8 +168,14 @@ macro_rules! try {
     })
 }
 
-/// Use the `format!` syntax to write data into a buffer of type `&mut Write`.
-/// See `std::fmt` for more information.
+/// Use the `format!` syntax to write data into a buffer.
+///
+/// This macro is typically used with a buffer of `&mut `[`Write`][write].
+///
+/// See [`std::fmt`][fmt] for more information on format syntax.
+///
+/// [fmt]: fmt/index.html
+/// [write]: io/trait.Write.html
 ///
 /// # Examples
 ///
@@ -179,14 +185,34 @@ macro_rules! try {
 /// let mut w = Vec::new();
 /// write!(&mut w, "test").unwrap();
 /// write!(&mut w, "formatted {}", "arguments").unwrap();
+///
+/// assert_eq!(w, b"testformatted arguments");
 /// ```
 #[macro_export]
 macro_rules! write {
     ($dst:expr, $($arg:tt)*) => ($dst.write_fmt(format_args!($($arg)*)))
 }
 
-/// Equivalent to the `write!` macro, except that a newline is appended after
-/// the message is written.
+/// Use the `format!` syntax to write data into a buffer, appending a newline.
+///
+/// This macro is typically used with a buffer of `&mut `[`Write`][write].
+///
+/// See [`std::fmt`][fmt] for more information on format syntax.
+///
+/// [fmt]: fmt/index.html
+/// [write]: io/trait.Write.html
+///
+/// # Examples
+///
+/// ```
+/// use std::io::Write;
+///
+/// let mut w = Vec::new();
+/// writeln!(&mut w, "test").unwrap();
+/// writeln!(&mut w, "formatted {}", "arguments").unwrap();
+///
+/// assert_eq!(&w[..], "test\nformatted arguments\n".as_bytes());
+/// ```
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! writeln {
@@ -253,7 +279,7 @@ macro_rules! unreachable {
     });
 }
 
-/// A standardised placeholder for marking unfinished code. It panics with the
+/// A standardized placeholder for marking unfinished code. It panics with the
 /// message `"not yet implemented"` when executed.
 ///
 /// This can be useful if you are prototyping and are just looking to have your
index 35dde63e52b52a37494f3e58233ee46211b154a8..27d8af2e8a88f28b23fee1130f2171091519432d 100644 (file)
@@ -36,6 +36,17 @@ impl<T> !Send for *const T { }
 impl<T> !Send for *mut T { }
 
 /// Types with a constant size known at compile-time.
+///
+/// All type parameters which can be bounded have an implicit bound of `Sized`. The special syntax
+/// `?Sized` can be used to remove this bound if it is not appropriate.
+///
+/// ```
+/// struct Foo<T>(T);
+/// struct Bar<T: ?Sized>(T);
+///
+/// // struct FooUse(Foo<[i32]>); // error: Sized is not implemented for [i32]
+/// struct BarUse(Bar<[i32]>); // OK
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[lang = "sized"]
 #[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
@@ -172,7 +183,7 @@ pub trait Copy : Clone {
 ///
 /// A somewhat surprising consequence of the definition is `&mut T` is
 /// `Sync` (if `T` is `Sync`) even though it seems that it might
-/// provide unsynchronised mutation. The trick is a mutable reference
+/// provide unsynchronized mutation. The trick is a mutable reference
 /// stored in an aliasable reference (that is, `& &mut T`) becomes
 /// read-only, as if it were a `& &T`, hence there is no risk of a data
 /// race.
@@ -195,7 +206,7 @@ pub trait Copy : Clone {
 ///
 /// Any types with interior mutability must also use the `std::cell::UnsafeCell`
 /// wrapper around the value(s) which can be mutated when behind a `&`
-/// reference; not doing this is undefined behaviour (for example,
+/// reference; not doing this is undefined behavior (for example,
 /// `transmute`-ing from `&T` to `&mut T` is invalid).
 #[stable(feature = "rust1", since = "1.0.0")]
 #[lang = "sync"]
@@ -381,7 +392,7 @@ mod impls {
 /// ```
 ///
 /// Without the declaration `T:Reflect`, `foo` would not type check
-/// (note: as a matter of style, it would be preferable to to write
+/// (note: as a matter of style, it would be preferable to write
 /// `T:Any`, because `T:Any` implies `T:Reflect` and `T:'static`, but
 /// we use `Reflect` here to show how it works). The `Reflect` bound
 /// thus serves to alert `foo`'s caller to the fact that `foo` may
index 48d003c2cffbab672cced53cab0eff87b4fd0e58..a87d135e42592551f518118a93969ca1ad6e436a 100644 (file)
@@ -37,7 +37,7 @@ pub use intrinsics::transmute;
 /// * You have two copies of a value (like when writing something like
 ///   [`mem::swap`][swap]), but need the destructor to only run once to
 ///   prevent a double `free`.
-/// * Transferring resources across [FFI][ffi] boundries.
+/// * Transferring resources across [FFI][ffi] boundaries.
 ///
 /// [swap]: fn.swap.html
 /// [ffi]: ../../book/ffi.html
@@ -264,9 +264,9 @@ pub unsafe fn dropped<T>() -> T {
 /// This is useful for FFI functions and initializing arrays sometimes,
 /// but should generally be avoided.
 ///
-/// # Undefined Behaviour
+/// # Undefined Behavior
 ///
-/// It is Undefined Behaviour to read uninitialized memory. Even just an
+/// It is Undefined Behavior to read uninitialized memory. Even just an
 /// uninitialized boolean. For instance, if you branch on the value of such
 /// a boolean your program may take one, both, or neither of the branches.
 ///
@@ -303,7 +303,7 @@ pub unsafe fn dropped<T>() -> T {
 ///
 ///     // DANGER ZONE: if anything panics or otherwise
 ///     // incorrectly reads the array here, we will have
-///     // Undefined Behaviour.
+///     // Undefined Behavior.
 ///
 ///     // It's ok to mutably iterate the data, since this
 ///     // doesn't involve reading it at all.
@@ -340,7 +340,7 @@ pub unsafe fn uninitialized<T>() -> T {
     intrinsics::uninit()
 }
 
-/// Swap the values at two mutable locations of the same type, without deinitialising or copying
+/// Swap the values at two mutable locations of the same type, without deinitializing or copying
 /// either one.
 ///
 /// # Examples
@@ -376,7 +376,7 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
 }
 
 /// Replaces the value at a mutable location with a new one, returning the old value, without
-/// deinitialising or copying either one.
+/// deinitializing or copying either one.
 ///
 /// This is primarily used for transferring and swapping ownership of a value in a mutable
 /// location.
@@ -434,6 +434,11 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
 /// While this does call the argument's implementation of `Drop`, it will not
 /// release any borrows, as borrows are based on lexical scope.
 ///
+/// This effectively does nothing for
+/// [types which implement `Copy`](../../book/ownership.html#copy-types),
+/// e.g. integers. Such values are copied and _then_ moved into the function,
+/// so the value persists after this function call.
+///
 /// # Examples
 ///
 /// Basic usage:
@@ -486,6 +491,21 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
 /// let borrow = x.borrow();
 /// println!("{}", *borrow);
 /// ```
+///
+/// Integers and other types implementing `Copy` are unaffected by `drop()`
+///
+/// ```
+/// #[derive(Copy, Clone)]
+/// struct Foo(u8);
+///
+/// let x = 1;
+/// let y = Foo(2);
+/// drop(x); // a copy of `x` is moved and dropped
+/// drop(y); // a copy of `y` is moved and dropped
+///
+/// println!("x: {}, y: {}", x, y.0); // still available
+/// ```
+///
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn drop<T>(_x: T) { }
index c945e4e066159e9a558bf6ba2f0f0c4ba4777632..c4ca3fa384e968cfe7734df57b8aa52108418ea6 100644 (file)
@@ -38,13 +38,31 @@ unsafe impl Zeroable for u64 {}
 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
 pub struct NonZero<T: Zeroable>(T);
 
+#[cfg(stage0)]
+macro_rules! nonzero_new {
+    () => (
+        /// Creates an instance of NonZero with the provided value.
+        /// You must indeed ensure that the value is actually "non-zero".
+        #[inline(always)]
+        pub unsafe fn new(inner: T) -> NonZero<T> {
+            NonZero(inner)
+        }
+    )
+}
+#[cfg(not(stage0))]
+macro_rules! nonzero_new {
+    () => (
+        /// Creates an instance of NonZero with the provided value.
+        /// You must indeed ensure that the value is actually "non-zero".
+        #[inline(always)]
+        pub const unsafe fn new(inner: T) -> NonZero<T> {
+            NonZero(inner)
+        }
+    )
+}
+
 impl<T: Zeroable> NonZero<T> {
-    /// Creates an instance of NonZero with the provided value.
-    /// You must indeed ensure that the value is actually "non-zero".
-    #[inline(always)]
-    pub unsafe fn new(inner: T) -> NonZero<T> {
-        NonZero(inner)
-    }
+    nonzero_new!{}
 }
 
 impl<T: Zeroable> Deref for NonZero<T> {
diff --git a/src/libcore/num/bignum.rs b/src/libcore/num/bignum.rs
new file mode 100644 (file)
index 0000000..18b34e2
--- /dev/null
@@ -0,0 +1,497 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Custom arbitrary-precision number (bignum) implementation.
+//!
+//! This is designed to avoid the heap allocation at expense of stack memory.
+//! The most used bignum type, `Big32x40`, is limited by 32 × 40 = 1,280 bits
+//! and will take at most 160 bytes of stack memory. This is more than enough
+//! for round-tripping all possible finite `f64` values.
+//!
+//! In principle it is possible to have multiple bignum types for different
+//! inputs, but we don't do so to avoid the code bloat. Each bignum is still
+//! tracked for the actual usages, so it normally doesn't matter.
+
+// This module is only for dec2flt and flt2dec, and only public because of libcoretest.
+// It is not intended to ever be stabilized.
+#![doc(hidden)]
+#![unstable(feature = "core_private_bignum",
+            reason = "internal routines only exposed for testing",
+            issue = "0")]
+#![macro_use]
+
+use prelude::v1::*;
+
+use mem;
+use intrinsics;
+
+/// Arithmetic operations required by bignums.
+pub trait FullOps {
+    /// Returns `(carry', v')` such that `carry' * 2^W + v' = self + other + carry`,
+    /// where `W` is the number of bits in `Self`.
+    fn full_add(self, other: Self, carry: bool) -> (bool /*carry*/, Self);
+
+    /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + carry`,
+    /// where `W` is the number of bits in `Self`.
+    fn full_mul(self, other: Self, carry: Self) -> (Self /*carry*/, Self);
+
+    /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + other2 + carry`,
+    /// where `W` is the number of bits in `Self`.
+    fn full_mul_add(self, other: Self, other2: Self, carry: Self) -> (Self /*carry*/, Self);
+
+    /// Returns `(quo, rem)` such that `borrow * 2^W + self = quo * other + rem`
+    /// and `0 <= rem < other`, where `W` is the number of bits in `Self`.
+    fn full_div_rem(self, other: Self, borrow: Self) -> (Self /*quotient*/, Self /*remainder*/);
+}
+
+macro_rules! impl_full_ops {
+    ($($ty:ty: add($addfn:path), mul/div($bigty:ident);)*) => (
+        $(
+            impl FullOps for $ty {
+                fn full_add(self, other: $ty, carry: bool) -> (bool, $ty) {
+                    // this cannot overflow, the output is between 0 and 2*2^nbits - 1
+                    // FIXME will LLVM optimize this into ADC or similar???
+                    let (v, carry1) = unsafe { $addfn(self, other) };
+                    let (v, carry2) = unsafe { $addfn(v, if carry {1} else {0}) };
+                    (carry1 || carry2, v)
+                }
+
+                fn full_mul(self, other: $ty, carry: $ty) -> ($ty, $ty) {
+                    // this cannot overflow, the output is between 0 and 2^nbits * (2^nbits - 1)
+                    let nbits = mem::size_of::<$ty>() * 8;
+                    let v = (self as $bigty) * (other as $bigty) + (carry as $bigty);
+                    ((v >> nbits) as $ty, v as $ty)
+                }
+
+                fn full_mul_add(self, other: $ty, other2: $ty, carry: $ty) -> ($ty, $ty) {
+                    // this cannot overflow, the output is between 0 and 2^(2*nbits) - 1
+                    let nbits = mem::size_of::<$ty>() * 8;
+                    let v = (self as $bigty) * (other as $bigty) + (other2 as $bigty) +
+                            (carry as $bigty);
+                    ((v >> nbits) as $ty, v as $ty)
+                }
+
+                fn full_div_rem(self, other: $ty, borrow: $ty) -> ($ty, $ty) {
+                    debug_assert!(borrow < other);
+                    // this cannot overflow, the dividend is between 0 and other * 2^nbits - 1
+                    let nbits = mem::size_of::<$ty>() * 8;
+                    let lhs = ((borrow as $bigty) << nbits) | (self as $bigty);
+                    let rhs = other as $bigty;
+                    ((lhs / rhs) as $ty, (lhs % rhs) as $ty)
+                }
+            }
+        )*
+    )
+}
+
+impl_full_ops! {
+    u8:  add(intrinsics::u8_add_with_overflow),  mul/div(u16);
+    u16: add(intrinsics::u16_add_with_overflow), mul/div(u32);
+    u32: add(intrinsics::u32_add_with_overflow), mul/div(u64);
+//  u64: add(intrinsics::u64_add_with_overflow), mul/div(u128); // see RFC #521 for enabling this.
+}
+
+/// Table of powers of 5 representable in digits. Specifically, the largest {u8, u16, u32} value
+/// that's a power of five, plus the corresponding exponent. Used in `mul_pow5`.
+const SMALL_POW5: [(u64, usize); 3] = [
+    (125, 3),
+    (15625, 6),
+    (1_220_703_125, 13),
+];
+
+macro_rules! define_bignum {
+    ($name:ident: type=$ty:ty, n=$n:expr) => (
+        /// Stack-allocated arbitrary-precision (up to certain limit) integer.
+        ///
+        /// This is backed by a fixed-size array of given type ("digit").
+        /// While the array is not very large (normally some hundred bytes),
+        /// copying it recklessly may result in the performance hit.
+        /// Thus this is intentionally not `Copy`.
+        ///
+        /// All operations available to bignums panic in the case of over/underflows.
+        /// The caller is responsible to use large enough bignum types.
+        pub struct $name {
+            /// One plus the offset to the maximum "digit" in use.
+            /// This does not decrease, so be aware of the computation order.
+            /// `base[size..]` should be zero.
+            size: usize,
+            /// Digits. `[a, b, c, ...]` represents `a + b*2^W + c*2^(2W) + ...`
+            /// where `W` is the number of bits in the digit type.
+            base: [$ty; $n]
+        }
+
+        impl $name {
+            /// Makes a bignum from one digit.
+            pub fn from_small(v: $ty) -> $name {
+                let mut base = [0; $n];
+                base[0] = v;
+                $name { size: 1, base: base }
+            }
+
+            /// Makes a bignum from `u64` value.
+            pub fn from_u64(mut v: u64) -> $name {
+                use mem;
+
+                let mut base = [0; $n];
+                let mut sz = 0;
+                while v > 0 {
+                    base[sz] = v as $ty;
+                    v >>= mem::size_of::<$ty>() * 8;
+                    sz += 1;
+                }
+                $name { size: sz, base: base }
+            }
+
+            /// Return the internal digits as a slice `[a, b, c, ...]` such that the numeric
+            /// value is `a + b * 2^W + c * 2^(2W) + ...` where `W` is the number of bits in
+            /// the digit type.
+            pub fn digits(&self) -> &[$ty] {
+                &self.base[..self.size]
+            }
+
+            /// Return the `i`-th bit where bit 0 is the least significant one.
+            /// In other words, the bit with weight `2^i`.
+            pub fn get_bit(&self, i: usize) -> u8 {
+                use mem;
+
+                let digitbits = mem::size_of::<$ty>() * 8;
+                let d = i / digitbits;
+                let b = i % digitbits;
+                ((self.base[d] >> b) & 1) as u8
+            }
+
+            /// Returns true if the bignum is zero.
+            pub fn is_zero(&self) -> bool {
+                self.digits().iter().all(|&v| v == 0)
+            }
+
+            /// Returns the number of bits necessary to represent this value. Note that zero
+            /// is considered to need 0 bits.
+            pub fn bit_length(&self) -> usize {
+                use mem;
+
+                // Skip over the most significant digits which are zero.
+                let digits = self.digits();
+                let zeros = digits.iter().rev().take_while(|&&x| x == 0).count();
+                let end = digits.len() - zeros;
+                let nonzero = &digits[..end];
+
+                if nonzero.is_empty() {
+                    // There are no non-zero digits, i.e. the number is zero.
+                    return 0;
+                }
+                // This could be optimized with leading_zeros() and bit shifts, but that's
+                // probably not worth the hassle.
+                let digitbits = mem::size_of::<$ty>()* 8;
+                let mut i = nonzero.len() * digitbits - 1;
+                while self.get_bit(i) == 0 {
+                    i -= 1;
+                }
+                i + 1
+            }
+
+            /// Adds `other` to itself and returns its own mutable reference.
+            pub fn add<'a>(&'a mut self, other: &$name) -> &'a mut $name {
+                use cmp;
+                use num::bignum::FullOps;
+
+                let mut sz = cmp::max(self.size, other.size);
+                let mut carry = false;
+                for (a, b) in self.base[..sz].iter_mut().zip(&other.base[..sz]) {
+                    let (c, v) = (*a).full_add(*b, carry);
+                    *a = v;
+                    carry = c;
+                }
+                if carry {
+                    self.base[sz] = 1;
+                    sz += 1;
+                }
+                self.size = sz;
+                self
+            }
+
+            pub fn add_small(&mut self, other: $ty) -> &mut $name {
+                use num::bignum::FullOps;
+
+                let (mut carry, v) = self.base[0].full_add(other, false);
+                self.base[0] = v;
+                let mut i = 1;
+                while carry {
+                    let (c, v) = self.base[i].full_add(0, carry);
+                    self.base[i] = v;
+                    carry = c;
+                    i += 1;
+                }
+                if i > self.size {
+                    self.size = i;
+                }
+                self
+            }
+
+            /// Subtracts `other` from itself and returns its own mutable reference.
+            pub fn sub<'a>(&'a mut self, other: &$name) -> &'a mut $name {
+                use cmp;
+                use num::bignum::FullOps;
+
+                let sz = cmp::max(self.size, other.size);
+                let mut noborrow = true;
+                for (a, b) in self.base[..sz].iter_mut().zip(&other.base[..sz]) {
+                    let (c, v) = (*a).full_add(!*b, noborrow);
+                    *a = v;
+                    noborrow = c;
+                }
+                assert!(noborrow);
+                self.size = sz;
+                self
+            }
+
+            /// Multiplies itself by a digit-sized `other` and returns its own
+            /// mutable reference.
+            pub fn mul_small(&mut self, other: $ty) -> &mut $name {
+                use num::bignum::FullOps;
+
+                let mut sz = self.size;
+                let mut carry = 0;
+                for a in &mut self.base[..sz] {
+                    let (c, v) = (*a).full_mul(other, carry);
+                    *a = v;
+                    carry = c;
+                }
+                if carry > 0 {
+                    self.base[sz] = carry;
+                    sz += 1;
+                }
+                self.size = sz;
+                self
+            }
+
+            /// Multiplies itself by `2^bits` and returns its own mutable reference.
+            pub fn mul_pow2(&mut self, bits: usize) -> &mut $name {
+                use mem;
+
+                let digitbits = mem::size_of::<$ty>() * 8;
+                let digits = bits / digitbits;
+                let bits = bits % digitbits;
+
+                assert!(digits < $n);
+                debug_assert!(self.base[$n-digits..].iter().all(|&v| v == 0));
+                debug_assert!(bits == 0 || (self.base[$n-digits-1] >> (digitbits - bits)) == 0);
+
+                // shift by `digits * digitbits` bits
+                for i in (0..self.size).rev() {
+                    self.base[i+digits] = self.base[i];
+                }
+                for i in 0..digits {
+                    self.base[i] = 0;
+                }
+
+                // shift by `bits` bits
+                let mut sz = self.size + digits;
+                if bits > 0 {
+                    let last = sz;
+                    let overflow = self.base[last-1] >> (digitbits - bits);
+                    if overflow > 0 {
+                        self.base[last] = overflow;
+                        sz += 1;
+                    }
+                    for i in (digits+1..last).rev() {
+                        self.base[i] = (self.base[i] << bits) |
+                                       (self.base[i-1] >> (digitbits - bits));
+                    }
+                    self.base[digits] <<= bits;
+                    // self.base[..digits] is zero, no need to shift
+                }
+
+                self.size = sz;
+                self
+            }
+
+            /// Multiplies itself by `5^e` and returns its own mutable reference.
+            pub fn mul_pow5(&mut self, mut e: usize) -> &mut $name {
+                use mem;
+                use num::bignum::SMALL_POW5;
+
+                // There are exactly n trailing zeros on 2^n, and the only relevant digit sizes
+                // are consecutive powers of two, so this is well suited index for the table.
+                let table_index = mem::size_of::<$ty>().trailing_zeros() as usize;
+                let (small_power, small_e) = SMALL_POW5[table_index];
+                let small_power = small_power as $ty;
+
+                // Multiply with the largest single-digit power as long as possible ...
+                while e >= small_e {
+                    self.mul_small(small_power);
+                    e -= small_e;
+                }
+
+                // ... then finish off the remainder.
+                let mut rest_power = 1;
+                for _ in 0..e {
+                    rest_power *= 5;
+                }
+                self.mul_small(rest_power);
+
+                self
+            }
+
+
+            /// Multiplies itself by a number described by `other[0] + other[1] * 2^W +
+            /// other[2] * 2^(2W) + ...` (where `W` is the number of bits in the digit type)
+            /// and returns its own mutable reference.
+            pub fn mul_digits<'a>(&'a mut self, other: &[$ty]) -> &'a mut $name {
+                // the internal routine. works best when aa.len() <= bb.len().
+                fn mul_inner(ret: &mut [$ty; $n], aa: &[$ty], bb: &[$ty]) -> usize {
+                    use num::bignum::FullOps;
+
+                    let mut retsz = 0;
+                    for (i, &a) in aa.iter().enumerate() {
+                        if a == 0 { continue; }
+                        let mut sz = bb.len();
+                        let mut carry = 0;
+                        for (j, &b) in bb.iter().enumerate() {
+                            let (c, v) = a.full_mul_add(b, ret[i + j], carry);
+                            ret[i + j] = v;
+                            carry = c;
+                        }
+                        if carry > 0 {
+                            ret[i + sz] = carry;
+                            sz += 1;
+                        }
+                        if retsz < i + sz {
+                            retsz = i + sz;
+                        }
+                    }
+                    retsz
+                }
+
+                let mut ret = [0; $n];
+                let retsz = if self.size < other.len() {
+                    mul_inner(&mut ret, &self.digits(), other)
+                } else {
+                    mul_inner(&mut ret, other, &self.digits())
+                };
+                self.base = ret;
+                self.size = retsz;
+                self
+            }
+
+            /// Divides itself by a digit-sized `other` and returns its own
+            /// mutable reference *and* the remainder.
+            pub fn div_rem_small(&mut self, other: $ty) -> (&mut $name, $ty) {
+                use num::bignum::FullOps;
+
+                assert!(other > 0);
+
+                let sz = self.size;
+                let mut borrow = 0;
+                for a in self.base[..sz].iter_mut().rev() {
+                    let (q, r) = (*a).full_div_rem(other, borrow);
+                    *a = q;
+                    borrow = r;
+                }
+                (self, borrow)
+            }
+
+            /// Divide self by another bignum, overwriting `q` with the quotient and `r` with the
+            /// remainder.
+            pub fn div_rem(&self, d: &$name, q: &mut $name, r: &mut $name) {
+                use mem;
+
+                // Stupid slow base-2 long division taken from
+                // https://en.wikipedia.org/wiki/Division_algorithm
+                // FIXME use a greater base ($ty) for the long division.
+                assert!(!d.is_zero());
+                let digitbits = mem::size_of::<$ty>() * 8;
+                for digit in &mut q.base[..] {
+                    *digit = 0;
+                }
+                for digit in &mut r.base[..] {
+                    *digit = 0;
+                }
+                r.size = d.size;
+                q.size = 1;
+                let mut q_is_zero = true;
+                let end = self.bit_length();
+                for i in (0..end).rev() {
+                    r.mul_pow2(1);
+                    r.base[0] |= self.get_bit(i) as $ty;
+                    if &*r >= d {
+                        r.sub(d);
+                        // Set bit `i` of q to 1.
+                        let digit_idx = i / digitbits;
+                        let bit_idx = i % digitbits;
+                        if q_is_zero {
+                            q.size = digit_idx + 1;
+                            q_is_zero = false;
+                        }
+                        q.base[digit_idx] |= 1 << bit_idx;
+                    }
+                }
+                debug_assert!(q.base[q.size..].iter().all(|&d| d == 0));
+                debug_assert!(r.base[r.size..].iter().all(|&d| d == 0));
+            }
+        }
+
+        impl ::cmp::PartialEq for $name {
+            fn eq(&self, other: &$name) -> bool { self.base[..] == other.base[..] }
+        }
+
+        impl ::cmp::Eq for $name {
+        }
+
+        impl ::cmp::PartialOrd for $name {
+            fn partial_cmp(&self, other: &$name) -> ::option::Option<::cmp::Ordering> {
+                ::option::Option::Some(self.cmp(other))
+            }
+        }
+
+        impl ::cmp::Ord for $name {
+            fn cmp(&self, other: &$name) -> ::cmp::Ordering {
+                use cmp::max;
+                let sz = max(self.size, other.size);
+                let lhs = self.base[..sz].iter().cloned().rev();
+                let rhs = other.base[..sz].iter().cloned().rev();
+                lhs.cmp(rhs)
+            }
+        }
+
+        impl ::clone::Clone for $name {
+            fn clone(&self) -> $name {
+                $name { size: self.size, base: self.base }
+            }
+        }
+
+        impl ::fmt::Debug for $name {
+            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+                use mem;
+
+                let sz = if self.size < 1 {1} else {self.size};
+                let digitlen = mem::size_of::<$ty>() * 2;
+
+                try!(write!(f, "{:#x}", self.base[sz-1]));
+                for &v in self.base[..sz-1].iter().rev() {
+                    try!(write!(f, "_{:01$x}", v, digitlen));
+                }
+                ::result::Result::Ok(())
+            }
+        }
+    )
+}
+
+/// The digit type for `Big32x40`.
+pub type Digit32 = u32;
+
+define_bignum!(Big32x40: type=Digit32, n=40);
+
+// this one is used for testing only.
+#[doc(hidden)]
+pub mod tests {
+    use prelude::v1::*;
+    define_bignum!(Big8x3: type=u8, n=3);
+}
index f166bb9b3eb8deee0862b0a56f0b6dfd61879eee..1f0f06d746197151f704f818a50de782b6d67b91 100644 (file)
 
 //! The various algorithms from the paper.
 
-use num::flt2dec::strategy::grisu::Fp;
 use prelude::v1::*;
 use cmp::min;
 use cmp::Ordering::{Less, Equal, Greater};
-use super::table;
-use super::rawfp::{self, Unpacked, RawFloat, fp_to_float, next_float, prev_float};
-use super::num::{self, Big};
+use num::diy_float::Fp;
+use num::dec2flt::table;
+use num::dec2flt::rawfp::{self, Unpacked, RawFloat, fp_to_float, next_float, prev_float};
+use num::dec2flt::num::{self, Big};
 
 /// Number of significand bits in Fp
 const P: u32 = 64;
index 4e6b6f04e9e9225a522a96bb705ad5d3f23f3eeb..55be4cd31910baedc5b547c1b9a1a0f3b728efd5 100644 (file)
@@ -86,9 +86,6 @@
 //! "such that the exponent +/- the number of decimal digits fits into a 64 bit integer".
 //! Larger exponents are accepted, but we don't do arithmetic with them, they are immediately
 //! turned into {positive,negative} {zero,infinity}.
-//!
-//! FIXME: this uses several things from core::num::flt2dec, which is nonsense. Those things
-//! should be moved into core::num::<something else>.
 
 #![doc(hidden)]
 #![unstable(feature = "dec2flt",
index dcba73d7c93221a687e91c8f50b513dcadd743e9..81e7856633b2571f9f0a33c2295671deefc1bda9 100644 (file)
@@ -14,9 +14,8 @@
 
 use prelude::v1::*;
 use cmp::Ordering::{self, Less, Equal, Greater};
-use num::flt2dec::bignum::Big32x40;
 
-pub type Big = Big32x40;
+pub use num::bignum::Big32x40 as Big;
 
 /// Test whether truncating all bits less significant than `ones_place` introduces
 /// a relative error less, equal, or greater than 0.5 ULP.
index 830d2dad42fe50de464bfbb010be0d7c68d16b80..be61653c37937f161e4cffad5fbf90b2abe96007 100644 (file)
@@ -33,10 +33,10 @@ use cmp::Ordering::{Less, Equal, Greater};
 use ops::{Mul, Div, Neg};
 use fmt::{Debug, LowerExp};
 use mem::transmute;
-use num::flt2dec::strategy::grisu::Fp;
+use num::diy_float::Fp;
 use num::FpCategory::{Infinite, Zero, Subnormal, Normal, Nan};
 use num::Float;
-use super::num::{self, Big};
+use num::dec2flt::num::{self, Big};
 
 #[derive(Copy, Clone, Debug)]
 pub struct Unpacked {
diff --git a/src/libcore/num/diy_float.rs b/src/libcore/num/diy_float.rs
new file mode 100644 (file)
index 0000000..7c369ee
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Extended precision "soft float", for internal use only.
+
+// This module is only for dec2flt and flt2dec, and only public because of libcoretest.
+// It is not intended to ever be stabilized.
+#![doc(hidden)]
+#![unstable(feature = "core_private_diy_float",
+            reason = "internal routines only exposed for testing",
+            issue = "0")]
+
+/// A custom 64-bit floating point type, representing `f * 2^e`.
+#[derive(Copy, Clone, Debug)]
+#[doc(hidden)]
+pub struct Fp {
+    /// The integer mantissa.
+    pub f: u64,
+    /// The exponent in base 2.
+    pub e: i16,
+}
+
+impl Fp {
+    /// Returns a correctly rounded product of itself and `other`.
+    pub fn mul(&self, other: &Fp) -> Fp {
+        const MASK: u64 = 0xffffffff;
+        let a = self.f >> 32;
+        let b = self.f & MASK;
+        let c = other.f >> 32;
+        let d = other.f & MASK;
+        let ac = a * c;
+        let bc = b * c;
+        let ad = a * d;
+        let bd = b * d;
+        let tmp = (bd >> 32) + (ad & MASK) + (bc & MASK) + (1 << 31) /* round */;
+        let f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
+        let e = self.e + other.e + 64;
+        Fp { f: f, e: e }
+    }
+
+    /// Normalizes itself so that the resulting mantissa is at least `2^63`.
+    pub fn normalize(&self) -> Fp {
+        let mut f = self.f;
+        let mut e = self.e;
+        if f >> (64 - 32) == 0 { f <<= 32; e -= 32; }
+        if f >> (64 - 16) == 0 { f <<= 16; e -= 16; }
+        if f >> (64 -  8) == 0 { f <<=  8; e -=  8; }
+        if f >> (64 -  4) == 0 { f <<=  4; e -=  4; }
+        if f >> (64 -  2) == 0 { f <<=  2; e -=  2; }
+        if f >> (64 -  1) == 0 { f <<=  1; e -=  1; }
+        debug_assert!(f >= (1 >> 63));
+        Fp { f: f, e: e }
+    }
+
+    /// Normalizes itself to have the shared exponent.
+    /// It can only decrease the exponent (and thus increase the mantissa).
+    pub fn normalize_to(&self, e: i16) -> Fp {
+        let edelta = self.e - e;
+        assert!(edelta >= 0);
+        let edelta = edelta as usize;
+        assert_eq!(self.f << edelta >> edelta, self.f);
+        Fp { f: self.f << edelta, e: e }
+    }
+}
index 1b7cbb050d1d93ea0108f07f13f5441c3f674b66..6185823d00132b5e970952769dd3c87a9afe3bff 100644 (file)
@@ -71,7 +71,7 @@ pub const INFINITY: f32 = 1.0_f32/0.0_f32;
 #[allow(missing_docs)]
 pub const NEG_INFINITY: f32 = -1.0_f32/0.0_f32;
 
-/// Basic mathematial constants.
+/// Basic mathematical constants.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub mod consts {
     // FIXME: replace with mathematical constants from cmath.
index a057e5fe51a7d6c1003048dd6cbc3414c38ed424..f85f8c5bd14333d1ee50b6e5514e527d4be51cf7 100644 (file)
@@ -71,7 +71,7 @@ pub const INFINITY: f64 = 1.0_f64/0.0_f64;
 #[allow(missing_docs)]
 pub const NEG_INFINITY: f64 = -1.0_f64/0.0_f64;
 
-/// Basic mathematial constants.
+/// Basic mathematical constants.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub mod consts {
     // FIXME: replace with mathematical constants from cmath.
diff --git a/src/libcore/num/flt2dec/bignum.rs b/src/libcore/num/flt2dec/bignum.rs
deleted file mode 100644 (file)
index 091e9c8..0000000
+++ /dev/null
@@ -1,491 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Custom arbitrary-precision number (bignum) implementation.
-//!
-//! This is designed to avoid the heap allocation at expense of stack memory.
-//! The most used bignum type, `Big32x40`, is limited by 32 × 40 = 1,280 bits
-//! and will take at most 160 bytes of stack memory. This is more than enough
-//! for round-tripping all possible finite `f64` values.
-//!
-//! In principle it is possible to have multiple bignum types for different
-//! inputs, but we don't do so to avoid the code bloat. Each bignum is still
-//! tracked for the actual usages, so it normally doesn't matter.
-
-#![macro_use]
-
-use prelude::v1::*;
-
-use mem;
-use intrinsics;
-
-/// Arithmetic operations required by bignums.
-pub trait FullOps {
-    /// Returns `(carry', v')` such that `carry' * 2^W + v' = self + other + carry`,
-    /// where `W` is the number of bits in `Self`.
-    fn full_add(self, other: Self, carry: bool) -> (bool /*carry*/, Self);
-
-    /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + carry`,
-    /// where `W` is the number of bits in `Self`.
-    fn full_mul(self, other: Self, carry: Self) -> (Self /*carry*/, Self);
-
-    /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + other2 + carry`,
-    /// where `W` is the number of bits in `Self`.
-    fn full_mul_add(self, other: Self, other2: Self, carry: Self) -> (Self /*carry*/, Self);
-
-    /// Returns `(quo, rem)` such that `borrow * 2^W + self = quo * other + rem`
-    /// and `0 <= rem < other`, where `W` is the number of bits in `Self`.
-    fn full_div_rem(self, other: Self, borrow: Self) -> (Self /*quotient*/, Self /*remainder*/);
-}
-
-macro_rules! impl_full_ops {
-    ($($ty:ty: add($addfn:path), mul/div($bigty:ident);)*) => (
-        $(
-            impl FullOps for $ty {
-                fn full_add(self, other: $ty, carry: bool) -> (bool, $ty) {
-                    // this cannot overflow, the output is between 0 and 2*2^nbits - 1
-                    // FIXME will LLVM optimize this into ADC or similar???
-                    let (v, carry1) = unsafe { $addfn(self, other) };
-                    let (v, carry2) = unsafe { $addfn(v, if carry {1} else {0}) };
-                    (carry1 || carry2, v)
-                }
-
-                fn full_mul(self, other: $ty, carry: $ty) -> ($ty, $ty) {
-                    // this cannot overflow, the output is between 0 and 2^nbits * (2^nbits - 1)
-                    let nbits = mem::size_of::<$ty>() * 8;
-                    let v = (self as $bigty) * (other as $bigty) + (carry as $bigty);
-                    ((v >> nbits) as $ty, v as $ty)
-                }
-
-                fn full_mul_add(self, other: $ty, other2: $ty, carry: $ty) -> ($ty, $ty) {
-                    // this cannot overflow, the output is between 0 and 2^(2*nbits) - 1
-                    let nbits = mem::size_of::<$ty>() * 8;
-                    let v = (self as $bigty) * (other as $bigty) + (other2 as $bigty) +
-                            (carry as $bigty);
-                    ((v >> nbits) as $ty, v as $ty)
-                }
-
-                fn full_div_rem(self, other: $ty, borrow: $ty) -> ($ty, $ty) {
-                    debug_assert!(borrow < other);
-                    // this cannot overflow, the dividend is between 0 and other * 2^nbits - 1
-                    let nbits = mem::size_of::<$ty>() * 8;
-                    let lhs = ((borrow as $bigty) << nbits) | (self as $bigty);
-                    let rhs = other as $bigty;
-                    ((lhs / rhs) as $ty, (lhs % rhs) as $ty)
-                }
-            }
-        )*
-    )
-}
-
-impl_full_ops! {
-    u8:  add(intrinsics::u8_add_with_overflow),  mul/div(u16);
-    u16: add(intrinsics::u16_add_with_overflow), mul/div(u32);
-    u32: add(intrinsics::u32_add_with_overflow), mul/div(u64);
-//  u64: add(intrinsics::u64_add_with_overflow), mul/div(u128); // see RFC #521 for enabling this.
-}
-
-/// Table of powers of 5 representable in digits. Specifically, the largest {u8, u16, u32} value
-/// that's a power of five, plus the corresponding exponent. Used in `mul_pow5`.
-const SMALL_POW5: [(u64, usize); 3] = [
-    (125, 3),
-    (15625, 6),
-    (1_220_703_125, 13),
-];
-
-macro_rules! define_bignum {
-    ($name:ident: type=$ty:ty, n=$n:expr) => (
-        /// Stack-allocated arbitrary-precision (up to certain limit) integer.
-        ///
-        /// This is backed by an fixed-size array of given type ("digit").
-        /// While the array is not very large (normally some hundred bytes),
-        /// copying it recklessly may result in the performance hit.
-        /// Thus this is intentionally not `Copy`.
-        ///
-        /// All operations available to bignums panic in the case of over/underflows.
-        /// The caller is responsible to use large enough bignum types.
-        pub struct $name {
-            /// One plus the offset to the maximum "digit" in use.
-            /// This does not decrease, so be aware of the computation order.
-            /// `base[size..]` should be zero.
-            size: usize,
-            /// Digits. `[a, b, c, ...]` represents `a + b*2^W + c*2^(2W) + ...`
-            /// where `W` is the number of bits in the digit type.
-            base: [$ty; $n]
-        }
-
-        impl $name {
-            /// Makes a bignum from one digit.
-            pub fn from_small(v: $ty) -> $name {
-                let mut base = [0; $n];
-                base[0] = v;
-                $name { size: 1, base: base }
-            }
-
-            /// Makes a bignum from `u64` value.
-            pub fn from_u64(mut v: u64) -> $name {
-                use mem;
-
-                let mut base = [0; $n];
-                let mut sz = 0;
-                while v > 0 {
-                    base[sz] = v as $ty;
-                    v >>= mem::size_of::<$ty>() * 8;
-                    sz += 1;
-                }
-                $name { size: sz, base: base }
-            }
-
-            /// Return the internal digits as a slice `[a, b, c, ...]` such that the numeric
-            /// value is `a + b * 2^W + c * 2^(2W) + ...` where `W` is the number of bits in
-            /// the digit type.
-            pub fn digits(&self) -> &[$ty] {
-                &self.base[..self.size]
-            }
-
-            /// Return the `i`-th bit where bit 0 is the least significant one.
-            /// In other words, the bit with weight `2^i`.
-            pub fn get_bit(&self, i: usize) -> u8 {
-                use mem;
-
-                let digitbits = mem::size_of::<$ty>() * 8;
-                let d = i / digitbits;
-                let b = i % digitbits;
-                ((self.base[d] >> b) & 1) as u8
-            }
-
-            /// Returns true if the bignum is zero.
-            pub fn is_zero(&self) -> bool {
-                self.digits().iter().all(|&v| v == 0)
-            }
-
-            /// Returns the number of bits necessary to represent this value. Note that zero
-            /// is considered to need 0 bits.
-            pub fn bit_length(&self) -> usize {
-                use mem;
-
-                // Skip over the most significant digits which are zero.
-                let digits = self.digits();
-                let zeros = digits.iter().rev().take_while(|&&x| x == 0).count();
-                let end = digits.len() - zeros;
-                let nonzero = &digits[..end];
-
-                if nonzero.is_empty() {
-                    // There are no non-zero digits, i.e. the number is zero.
-                    return 0;
-                }
-                // This could be optimized with leading_zeros() and bit shifts, but that's
-                // probably not worth the hassle.
-                let digitbits = mem::size_of::<$ty>()* 8;
-                let mut i = nonzero.len() * digitbits - 1;
-                while self.get_bit(i) == 0 {
-                    i -= 1;
-                }
-                i + 1
-            }
-
-            /// Adds `other` to itself and returns its own mutable reference.
-            pub fn add<'a>(&'a mut self, other: &$name) -> &'a mut $name {
-                use cmp;
-                use num::flt2dec::bignum::FullOps;
-
-                let mut sz = cmp::max(self.size, other.size);
-                let mut carry = false;
-                for (a, b) in self.base[..sz].iter_mut().zip(&other.base[..sz]) {
-                    let (c, v) = (*a).full_add(*b, carry);
-                    *a = v;
-                    carry = c;
-                }
-                if carry {
-                    self.base[sz] = 1;
-                    sz += 1;
-                }
-                self.size = sz;
-                self
-            }
-
-            pub fn add_small(&mut self, other: $ty) -> &mut $name {
-                use num::flt2dec::bignum::FullOps;
-
-                let (mut carry, v) = self.base[0].full_add(other, false);
-                self.base[0] = v;
-                let mut i = 1;
-                while carry {
-                    let (c, v) = self.base[i].full_add(0, carry);
-                    self.base[i] = v;
-                    carry = c;
-                    i += 1;
-                }
-                if i > self.size {
-                    self.size = i;
-                }
-                self
-            }
-
-            /// Subtracts `other` from itself and returns its own mutable reference.
-            pub fn sub<'a>(&'a mut self, other: &$name) -> &'a mut $name {
-                use cmp;
-                use num::flt2dec::bignum::FullOps;
-
-                let sz = cmp::max(self.size, other.size);
-                let mut noborrow = true;
-                for (a, b) in self.base[..sz].iter_mut().zip(&other.base[..sz]) {
-                    let (c, v) = (*a).full_add(!*b, noborrow);
-                    *a = v;
-                    noborrow = c;
-                }
-                assert!(noborrow);
-                self.size = sz;
-                self
-            }
-
-            /// Multiplies itself by a digit-sized `other` and returns its own
-            /// mutable reference.
-            pub fn mul_small(&mut self, other: $ty) -> &mut $name {
-                use num::flt2dec::bignum::FullOps;
-
-                let mut sz = self.size;
-                let mut carry = 0;
-                for a in &mut self.base[..sz] {
-                    let (c, v) = (*a).full_mul(other, carry);
-                    *a = v;
-                    carry = c;
-                }
-                if carry > 0 {
-                    self.base[sz] = carry;
-                    sz += 1;
-                }
-                self.size = sz;
-                self
-            }
-
-            /// Multiplies itself by `2^bits` and returns its own mutable reference.
-            pub fn mul_pow2(&mut self, bits: usize) -> &mut $name {
-                use mem;
-
-                let digitbits = mem::size_of::<$ty>() * 8;
-                let digits = bits / digitbits;
-                let bits = bits % digitbits;
-
-                assert!(digits < $n);
-                debug_assert!(self.base[$n-digits..].iter().all(|&v| v == 0));
-                debug_assert!(bits == 0 || (self.base[$n-digits-1] >> (digitbits - bits)) == 0);
-
-                // shift by `digits * digitbits` bits
-                for i in (0..self.size).rev() {
-                    self.base[i+digits] = self.base[i];
-                }
-                for i in 0..digits {
-                    self.base[i] = 0;
-                }
-
-                // shift by `bits` bits
-                let mut sz = self.size + digits;
-                if bits > 0 {
-                    let last = sz;
-                    let overflow = self.base[last-1] >> (digitbits - bits);
-                    if overflow > 0 {
-                        self.base[last] = overflow;
-                        sz += 1;
-                    }
-                    for i in (digits+1..last).rev() {
-                        self.base[i] = (self.base[i] << bits) |
-                                       (self.base[i-1] >> (digitbits - bits));
-                    }
-                    self.base[digits] <<= bits;
-                    // self.base[..digits] is zero, no need to shift
-                }
-
-                self.size = sz;
-                self
-            }
-
-            /// Multiplies itself by `5^e` and returns its own mutable reference.
-            pub fn mul_pow5(&mut self, mut e: usize) -> &mut $name {
-                use mem;
-                use num::flt2dec::bignum::SMALL_POW5;
-
-                // There are exactly n trailing zeros on 2^n, and the only relevant digit sizes
-                // are consecutive powers of two, so this is well suited index for the table.
-                let table_index = mem::size_of::<$ty>().trailing_zeros() as usize;
-                let (small_power, small_e) = SMALL_POW5[table_index];
-                let small_power = small_power as $ty;
-
-                // Multiply with the largest single-digit power as long as possible ...
-                while e >= small_e {
-                    self.mul_small(small_power);
-                    e -= small_e;
-                }
-
-                // ... then finish off the remainder.
-                let mut rest_power = 1;
-                for _ in 0..e {
-                    rest_power *= 5;
-                }
-                self.mul_small(rest_power);
-
-                self
-            }
-
-
-            /// Multiplies itself by a number described by `other[0] + other[1] * 2^W +
-            /// other[2] * 2^(2W) + ...` (where `W` is the number of bits in the digit type)
-            /// and returns its own mutable reference.
-            pub fn mul_digits<'a>(&'a mut self, other: &[$ty]) -> &'a mut $name {
-                // the internal routine. works best when aa.len() <= bb.len().
-                fn mul_inner(ret: &mut [$ty; $n], aa: &[$ty], bb: &[$ty]) -> usize {
-                    use num::flt2dec::bignum::FullOps;
-
-                    let mut retsz = 0;
-                    for (i, &a) in aa.iter().enumerate() {
-                        if a == 0 { continue; }
-                        let mut sz = bb.len();
-                        let mut carry = 0;
-                        for (j, &b) in bb.iter().enumerate() {
-                            let (c, v) = a.full_mul_add(b, ret[i + j], carry);
-                            ret[i + j] = v;
-                            carry = c;
-                        }
-                        if carry > 0 {
-                            ret[i + sz] = carry;
-                            sz += 1;
-                        }
-                        if retsz < i + sz {
-                            retsz = i + sz;
-                        }
-                    }
-                    retsz
-                }
-
-                let mut ret = [0; $n];
-                let retsz = if self.size < other.len() {
-                    mul_inner(&mut ret, &self.digits(), other)
-                } else {
-                    mul_inner(&mut ret, other, &self.digits())
-                };
-                self.base = ret;
-                self.size = retsz;
-                self
-            }
-
-            /// Divides itself by a digit-sized `other` and returns its own
-            /// mutable reference *and* the remainder.
-            pub fn div_rem_small(&mut self, other: $ty) -> (&mut $name, $ty) {
-                use num::flt2dec::bignum::FullOps;
-
-                assert!(other > 0);
-
-                let sz = self.size;
-                let mut borrow = 0;
-                for a in self.base[..sz].iter_mut().rev() {
-                    let (q, r) = (*a).full_div_rem(other, borrow);
-                    *a = q;
-                    borrow = r;
-                }
-                (self, borrow)
-            }
-
-            /// Divide self by another bignum, overwriting `q` with the quotient and `r` with the
-            /// remainder.
-            pub fn div_rem(&self, d: &$name, q: &mut $name, r: &mut $name) {
-                use mem;
-
-                // Stupid slow base-2 long division taken from
-                // https://en.wikipedia.org/wiki/Division_algorithm
-                // FIXME use a greater base ($ty) for the long division.
-                assert!(!d.is_zero());
-                let digitbits = mem::size_of::<$ty>() * 8;
-                for digit in &mut q.base[..] {
-                    *digit = 0;
-                }
-                for digit in &mut r.base[..] {
-                    *digit = 0;
-                }
-                r.size = d.size;
-                q.size = 1;
-                let mut q_is_zero = true;
-                let end = self.bit_length();
-                for i in (0..end).rev() {
-                    r.mul_pow2(1);
-                    r.base[0] |= self.get_bit(i) as $ty;
-                    if &*r >= d {
-                        r.sub(d);
-                        // Set bit `i` of q to 1.
-                        let digit_idx = i / digitbits;
-                        let bit_idx = i % digitbits;
-                        if q_is_zero {
-                            q.size = digit_idx + 1;
-                            q_is_zero = false;
-                        }
-                        q.base[digit_idx] |= 1 << bit_idx;
-                    }
-                }
-                debug_assert!(q.base[q.size..].iter().all(|&d| d == 0));
-                debug_assert!(r.base[r.size..].iter().all(|&d| d == 0));
-            }
-        }
-
-        impl ::cmp::PartialEq for $name {
-            fn eq(&self, other: &$name) -> bool { self.base[..] == other.base[..] }
-        }
-
-        impl ::cmp::Eq for $name {
-        }
-
-        impl ::cmp::PartialOrd for $name {
-            fn partial_cmp(&self, other: &$name) -> ::option::Option<::cmp::Ordering> {
-                ::option::Option::Some(self.cmp(other))
-            }
-        }
-
-        impl ::cmp::Ord for $name {
-            fn cmp(&self, other: &$name) -> ::cmp::Ordering {
-                use cmp::max;
-                let sz = max(self.size, other.size);
-                let lhs = self.base[..sz].iter().cloned().rev();
-                let rhs = other.base[..sz].iter().cloned().rev();
-                lhs.cmp(rhs)
-            }
-        }
-
-        impl ::clone::Clone for $name {
-            fn clone(&self) -> $name {
-                $name { size: self.size, base: self.base }
-            }
-        }
-
-        impl ::fmt::Debug for $name {
-            fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
-                use mem;
-
-                let sz = if self.size < 1 {1} else {self.size};
-                let digitlen = mem::size_of::<$ty>() * 2;
-
-                try!(write!(f, "{:#x}", self.base[sz-1]));
-                for &v in self.base[..sz-1].iter().rev() {
-                    try!(write!(f, "_{:01$x}", v, digitlen));
-                }
-                ::result::Result::Ok(())
-            }
-        }
-    )
-}
-
-/// The digit type for `Big32x40`.
-pub type Digit32 = u32;
-
-define_bignum!(Big32x40: type=Digit32, n=40);
-
-// this one is used for testing only.
-#[doc(hidden)]
-pub mod tests {
-    use prelude::v1::*;
-    define_bignum!(Big8x3: type=u8, n=3);
-}
index 700523e49a2760273f3ce3ee05aa9ce4b93d62e7..57d4bccbfa68f1ab4a40f3662c374bd57e7cd00a 100644 (file)
@@ -136,7 +136,6 @@ use slice::bytes;
 pub use self::decoder::{decode, DecodableFloat, FullDecoded, Decoded};
 
 pub mod estimator;
-pub mod bignum;
 pub mod decoder;
 
 /// Digit-generation algorithms.
@@ -462,7 +461,7 @@ pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T,
 /// You probably would want `strategy::grisu::format_shortest` for this.
 ///
 /// The `dec_bounds` is a tuple `(lo, hi)` such that the number is formatted
-/// as decimal only when `10^lo <= V < 10^hi`. Note that this is the *apparant* `V`
+/// as decimal only when `10^lo <= V < 10^hi`. Note that this is the *apparent* `V`
 /// instead of the actual `v`! Thus any printed exponent in the exponential form
 /// cannot be in this range, avoiding any confusion.
 ///
index 40aa2a527dbc5607d4ead32b4a97fb8bbf6984c9..2d68c3a6d026ec397cd7fdd55ec849e961cf8d72 100644 (file)
@@ -21,8 +21,8 @@ use cmp::Ordering;
 
 use num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up};
 use num::flt2dec::estimator::estimate_scaling_factor;
-use num::flt2dec::bignum::Digit32 as Digit;
-use num::flt2dec::bignum::Big32x40 as Big;
+use num::bignum::Digit32 as Digit;
+use num::bignum::Big32x40 as Big;
 
 static POW10: [Digit; 10] = [1, 10, 100, 1000, 10000, 100000,
                              1000000, 10000000, 100000000, 1000000000];
index b0822ca76c76b8b2641fc80efb74bb23745e825b..13e01d9a7f7ab548918288fbbe693da00c980cf1 100644 (file)
@@ -18,60 +18,9 @@ Rust adaptation of Grisu3 algorithm described in [1]. It uses about
 
 use prelude::v1::*;
 
+use num::diy_float::Fp;
 use num::flt2dec::{Decoded, MAX_SIG_DIGITS, round_up};
 
-/// A custom 64-bit floating point type, representing `f * 2^e`.
-#[derive(Copy, Clone, Debug)]
-#[doc(hidden)]
-pub struct Fp {
-    /// The integer mantissa.
-    pub f: u64,
-    /// The exponent in base 2.
-    pub e: i16,
-}
-
-impl Fp {
-    /// Returns a correctly rounded product of itself and `other`.
-    pub fn mul(&self, other: &Fp) -> Fp {
-        const MASK: u64 = 0xffffffff;
-        let a = self.f >> 32;
-        let b = self.f & MASK;
-        let c = other.f >> 32;
-        let d = other.f & MASK;
-        let ac = a * c;
-        let bc = b * c;
-        let ad = a * d;
-        let bd = b * d;
-        let tmp = (bd >> 32) + (ad & MASK) + (bc & MASK) + (1 << 31) /* round */;
-        let f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
-        let e = self.e + other.e + 64;
-        Fp { f: f, e: e }
-    }
-
-    /// Normalizes itself so that the resulting mantissa is at least `2^63`.
-    pub fn normalize(&self) -> Fp {
-        let mut f = self.f;
-        let mut e = self.e;
-        if f >> (64 - 32) == 0 { f <<= 32; e -= 32; }
-        if f >> (64 - 16) == 0 { f <<= 16; e -= 16; }
-        if f >> (64 -  8) == 0 { f <<=  8; e -=  8; }
-        if f >> (64 -  4) == 0 { f <<=  4; e -=  4; }
-        if f >> (64 -  2) == 0 { f <<=  2; e -=  2; }
-        if f >> (64 -  1) == 0 { f <<=  1; e -=  1; }
-        debug_assert!(f >= (1 >> 63));
-        Fp { f: f, e: e }
-    }
-
-    /// Normalizes itself to have the shared exponent.
-    /// It can only decrease the exponent (and thus increase the mantissa).
-    pub fn normalize_to(&self, e: i16) -> Fp {
-        let edelta = self.e - e;
-        assert!(edelta >= 0);
-        let edelta = edelta as usize;
-        assert_eq!(self.f << edelta >> edelta, self.f);
-        Fp { f: self.f << edelta, e: e }
-    }
-}
 
 // see the comments in `format_shortest_opt` for the rationale.
 #[doc(hidden)] pub const ALPHA: i16 = -60;
@@ -539,7 +488,7 @@ pub fn format_exact_opt(d: &Decoded, buf: &mut [u8], limit: i16)
         // but scaling `max_ten_kappa << e` by 10 can result in overflow.
         // thus we are being sloppy here and widen the error range by a factor of 10.
         // this will increase the false negative rate, but only very, *very* slightly;
-        // it can only matter noticably when the mantissa is bigger than 60 bits.
+        // it can only matter noticeably when the mantissa is bigger than 60 bits.
         return possibly_round(buf, 0, exp, limit, v.f / 10, (max_ten_kappa as u64) << e, err << e);
     } else if ((exp as i32 - limit as i32) as usize) < buf.len() {
         (exp - limit) as usize
index 127f8d3b5a2d89ac832bc8bd293181fa43bd5318..de56cf902a4fd91d2d1dfb9d9a8163013e3b5127 100644 (file)
@@ -17,6 +17,7 @@ use self::wrapping::OverflowingOps;
 
 use char::CharExt;
 use cmp::{Eq, PartialOrd};
+use convert::From;
 use fmt;
 use intrinsics;
 use marker::{Copy, Sized};
@@ -39,12 +40,16 @@ use slice::SliceExt;
 /// all standard arithmetic operations on the underlying value are
 /// intended to have wrapping semantics.
 #[stable(feature = "rust1", since = "1.0.0")]
-#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
+#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Default)]
 pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T);
 
 pub mod wrapping;
+
+// All these modules are technically private and only exposed for libcoretest:
 pub mod flt2dec;
 pub mod dec2flt;
+pub mod bignum;
+pub mod diy_float;
 
 /// Types that have a "zero" value.
 ///
@@ -53,7 +58,7 @@ pub mod dec2flt;
 #[unstable(feature = "zero_one",
            reason = "unsure of placement, wants to use associated constants",
            issue = "27739")]
-pub trait Zero {
+pub trait Zero: Sized {
     /// The "zero" (usually, additive identity) for this type.
     fn zero() -> Self;
 }
@@ -65,7 +70,7 @@ pub trait Zero {
 #[unstable(feature = "zero_one",
            reason = "unsure of placement, wants to use associated constants",
            issue = "27739")]
-pub trait One {
+pub trait One: Sized {
     /// The "one" (usually, multiplicative identity) for this type.
     fn one() -> Self;
 }
@@ -399,12 +404,12 @@ macro_rules! int_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn checked_div(self, v: Self) -> Option<Self> {
-            match v {
-                0   => None,
+        pub fn checked_div(self, other: Self) -> Option<Self> {
+            match other {
+                0    => None,
                -1 if self == Self::min_value()
-                    => None,
-                v   => Some(self / v),
+                     => None,
+               other => Some(self / other),
             }
         }
 
@@ -968,10 +973,10 @@ macro_rules! uint_impl {
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
-        pub fn checked_div(self, v: Self) -> Option<Self> {
-            match v {
+        pub fn checked_div(self, other: Self) -> Option<Self> {
+            match other {
                 0 => None,
-                v => Some(self / v),
+                other => Some(self / other),
             }
         }
 
@@ -1379,54 +1384,55 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32)
 
     // all valid digits are ascii, so we will just iterate over the utf8 bytes
     // and cast them to chars. .to_digit() will safely return None for anything
-    // other than a valid ascii digit for the given radix, including the first-byte
+    // other than a valid ascii digit for the given radix, including the first-byte
     // of multi-byte sequences
     let src = src.as_bytes();
 
-    match (src[0], &src[1..])  {
-        (b'-', digits) if digits.is_empty() => Err(PIE { kind: Empty }),
-        (b'-', digits) if is_signed_ty => {
-            // The number is negative
-            let mut result = T::from_u32(0);
-            for &c in digits {
-                let x = match (c as char).to_digit(radix) {
-                    Some(x) => x,
-                    None => return Err(PIE { kind: InvalidDigit }),
-                };
-                result = match result.checked_mul(radix) {
-                    Some(result) => result,
-                    None => return Err(PIE { kind: Underflow }),
-                };
-                result = match result.checked_sub(x) {
-                    Some(result) => result,
-                    None => return Err(PIE { kind: Underflow }),
-                };
-            }
-            Ok(result)
-        },
-        (c, digits) => {
-            // The number is signed
-            let mut result = match (c as char).to_digit(radix) {
-                Some(x) => T::from_u32(x),
+    let (is_positive, digits) = match src[0] {
+        b'+' => (true, &src[1..]),
+        b'-' if is_signed_ty => (false, &src[1..]),
+        _ => (true, src)
+    };
+
+    if digits.is_empty() {
+        return Err(PIE { kind: Empty });
+    }
+
+    let mut result = T::from_u32(0);
+    if is_positive {
+        // The number is positive
+        for &c in digits {
+            let x = match (c as char).to_digit(radix) {
+                Some(x) => x,
                 None => return Err(PIE { kind: InvalidDigit }),
             };
-            for &c in digits {
-                let x = match (c as char).to_digit(radix) {
-                    Some(x) => x,
-                    None => return Err(PIE { kind: InvalidDigit }),
-                };
-                result = match result.checked_mul(radix) {
-                    Some(result) => result,
-                    None => return Err(PIE { kind: Overflow }),
-                };
-                result = match result.checked_add(x) {
-                    Some(result) => result,
-                    None => return Err(PIE { kind: Overflow }),
-                };
-            }
-            Ok(result)
+            result = match result.checked_mul(radix) {
+                Some(result) => result,
+                None => return Err(PIE { kind: Overflow }),
+            };
+            result = match result.checked_add(x) {
+                Some(result) => result,
+                None => return Err(PIE { kind: Overflow }),
+            };
+        }
+    } else {
+        // The number is negative
+        for &c in digits {
+            let x = match (c as char).to_digit(radix) {
+                Some(x) => x,
+                None => return Err(PIE { kind: InvalidDigit }),
+            };
+            result = match result.checked_mul(radix) {
+                Some(result) => result,
+                None => return Err(PIE { kind: Underflow }),
+            };
+            result = match result.checked_sub(x) {
+                Some(result) => result,
+                None => return Err(PIE { kind: Underflow }),
+            };
         }
     }
+    Ok(result)
 }
 
 /// An error which can be returned when parsing an integer.
@@ -1466,3 +1472,45 @@ impl fmt::Display for ParseIntError {
 }
 
 pub use num::dec2flt::ParseFloatError;
+
+// Conversion traits for primitive integer types
+// Conversions T -> T are covered by a blanket impl and therefore excluded
+// Some conversions from and to usize/isize are not implemented due to portability concerns
+macro_rules! impl_from {
+    ($Small: ty, $Large: ty) => {
+        #[stable(feature = "lossless_int_conv", since = "1.5.0")]
+        impl From<$Small> for $Large {
+            #[stable(feature = "lossless_int_conv", since = "1.5.0")]
+            #[inline]
+            fn from(small: $Small) -> $Large {
+                small as $Large
+            }
+        }
+    }
+}
+
+// Unsigned -> Unsigned
+impl_from! { u8, u16 }
+impl_from! { u8, u32 }
+impl_from! { u8, u64 }
+impl_from! { u8, usize }
+impl_from! { u16, u32 }
+impl_from! { u16, u64 }
+impl_from! { u32, u64 }
+
+// Signed -> Signed
+impl_from! { i8, i16 }
+impl_from! { i8, i32 }
+impl_from! { i8, i64 }
+impl_from! { i8, isize }
+impl_from! { i16, i32 }
+impl_from! { i16, i64 }
+impl_from! { i32, i64 }
+
+// Unsigned -> Signed
+impl_from! { u8, i16 }
+impl_from! { u8, i32 }
+impl_from! { u8, i64 }
+impl_from! { u16, i32 }
+impl_from! { u16, i64 }
+impl_from! { u32, i64 }
index 07de4d0761baadf7db47c3bddb3f82199fc80bcf..582c091091fb2ac800de643d52936b48bb97b7c4 100644 (file)
@@ -94,7 +94,7 @@ use fmt;
 #[lang = "drop"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Drop {
-    /// The `drop` method, called when the value goes out of scope.
+    /// A method called when the value goes out of scope.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn drop(&mut self);
 }
@@ -927,6 +927,534 @@ macro_rules! shr_impl_all {
 
 shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
 
+/// The `AddAssign` trait is used to specify the functionality of `+=`.
+///
+/// # Examples
+///
+/// A trivial implementation of `AddAssign`. When `Foo += Foo` happens, it ends up
+/// calling `add_assign`, and therefore, `main` prints `Adding!`.
+///
+/// ```
+/// #![feature(augmented_assignments)]
+/// #![feature(op_assign_traits)]
+///
+/// use std::ops::AddAssign;
+///
+/// #[derive(Copy, Clone)]
+/// struct Foo;
+///
+/// impl AddAssign for Foo {
+///     fn add_assign(&mut self, _rhs: Foo) {
+///         println!("Adding!");
+///     }
+/// }
+///
+/// fn main() {
+///     let mut foo = Foo;
+///     foo += Foo;
+/// }
+/// ```
+#[cfg(not(stage0))]
+#[lang = "add_assign"]
+#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+pub trait AddAssign<Rhs=Self> {
+    /// The method for the `+=` operator
+    fn add_assign(&mut self, Rhs);
+}
+
+#[cfg(not(stage0))]
+macro_rules! add_assign_impl {
+    ($($t:ty)+) => ($(
+        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        impl AddAssign for $t {
+            #[inline]
+            fn add_assign(&mut self, other: $t) { *self += other }
+        }
+    )+)
+}
+
+#[cfg(not(stage0))]
+add_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
+
+/// The `SubAssign` trait is used to specify the functionality of `-=`.
+///
+/// # Examples
+///
+/// A trivial implementation of `SubAssign`. When `Foo -= Foo` happens, it ends up
+/// calling `sub_assign`, and therefore, `main` prints `Subtracting!`.
+///
+/// ```
+/// #![feature(augmented_assignments)]
+/// #![feature(op_assign_traits)]
+///
+/// use std::ops::SubAssign;
+///
+/// #[derive(Copy, Clone)]
+/// struct Foo;
+///
+/// impl SubAssign for Foo {
+///     fn sub_assign(&mut self, _rhs: Foo) {
+///         println!("Subtracting!");
+///     }
+/// }
+///
+/// fn main() {
+///     let mut foo = Foo;
+///     foo -= Foo;
+/// }
+/// ```
+#[cfg(not(stage0))]
+#[lang = "sub_assign"]
+#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+pub trait SubAssign<Rhs=Self> {
+    /// The method for the `-=` operator
+    fn sub_assign(&mut self, Rhs);
+}
+
+#[cfg(not(stage0))]
+macro_rules! sub_assign_impl {
+    ($($t:ty)+) => ($(
+        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        impl SubAssign for $t {
+            #[inline]
+            fn sub_assign(&mut self, other: $t) { *self -= other }
+        }
+    )+)
+}
+
+#[cfg(not(stage0))]
+sub_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
+
+/// The `MulAssign` trait is used to specify the functionality of `*=`.
+///
+/// # Examples
+///
+/// A trivial implementation of `MulAssign`. When `Foo *= Foo` happens, it ends up
+/// calling `mul_assign`, and therefore, `main` prints `Multiplying!`.
+///
+/// ```
+/// #![feature(augmented_assignments)]
+/// #![feature(op_assign_traits)]
+///
+/// use std::ops::MulAssign;
+///
+/// #[derive(Copy, Clone)]
+/// struct Foo;
+///
+/// impl MulAssign for Foo {
+///     fn mul_assign(&mut self, _rhs: Foo) {
+///         println!("Multiplying!");
+///     }
+/// }
+///
+/// fn main() {
+///     let mut foo = Foo;
+///     foo *= Foo;
+/// }
+/// ```
+#[cfg(not(stage0))]
+#[lang = "mul_assign"]
+#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+pub trait MulAssign<Rhs=Self> {
+    /// The method for the `*=` operator
+    fn mul_assign(&mut self, Rhs);
+}
+
+#[cfg(not(stage0))]
+macro_rules! mul_assign_impl {
+    ($($t:ty)+) => ($(
+        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        impl MulAssign for $t {
+            #[inline]
+            fn mul_assign(&mut self, other: $t) { *self *= other }
+        }
+    )+)
+}
+
+#[cfg(not(stage0))]
+mul_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
+
+/// The `DivAssign` trait is used to specify the functionality of `/=`.
+///
+/// # Examples
+///
+/// A trivial implementation of `DivAssign`. When `Foo /= Foo` happens, it ends up
+/// calling `div_assign`, and therefore, `main` prints `Dividing!`.
+///
+/// ```
+/// #![feature(augmented_assignments)]
+/// #![feature(op_assign_traits)]
+///
+/// use std::ops::DivAssign;
+///
+/// #[derive(Copy, Clone)]
+/// struct Foo;
+///
+/// impl DivAssign for Foo {
+///     fn div_assign(&mut self, _rhs: Foo) {
+///         println!("Dividing!");
+///     }
+/// }
+///
+/// fn main() {
+///     let mut foo = Foo;
+///     foo /= Foo;
+/// }
+/// ```
+#[cfg(not(stage0))]
+#[lang = "div_assign"]
+#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+pub trait DivAssign<Rhs=Self> {
+    /// The method for the `/=` operator
+    fn div_assign(&mut self, Rhs);
+}
+
+#[cfg(not(stage0))]
+macro_rules! div_assign_impl {
+    ($($t:ty)+) => ($(
+        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        impl DivAssign for $t {
+            #[inline]
+            fn div_assign(&mut self, other: $t) { *self /= other }
+        }
+    )+)
+}
+
+#[cfg(not(stage0))]
+div_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
+
+/// The `RemAssign` trait is used to specify the functionality of `%=`.
+///
+/// # Examples
+///
+/// A trivial implementation of `RemAssign`. When `Foo %= Foo` happens, it ends up
+/// calling `rem_assign`, and therefore, `main` prints `Remainder-ing!`.
+///
+/// ```
+/// #![feature(augmented_assignments)]
+/// #![feature(op_assign_traits)]
+///
+/// use std::ops::RemAssign;
+///
+/// #[derive(Copy, Clone)]
+/// struct Foo;
+///
+/// impl RemAssign for Foo {
+///     fn rem_assign(&mut self, _rhs: Foo) {
+///         println!("Remainder-ing!");
+///     }
+/// }
+///
+/// fn main() {
+///     let mut foo = Foo;
+///     foo %= Foo;
+/// }
+/// ```
+#[cfg(not(stage0))]
+#[lang = "rem_assign"]
+#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+pub trait RemAssign<Rhs=Self> {
+    /// The method for the `%=` operator
+    fn rem_assign(&mut self, Rhs);
+}
+
+#[cfg(not(stage0))]
+macro_rules! rem_assign_impl {
+    ($($t:ty)+) => ($(
+        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        impl RemAssign for $t {
+            #[inline]
+            fn rem_assign(&mut self, other: $t) { *self %= other }
+        }
+    )+)
+}
+
+#[cfg(not(stage0))]
+rem_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
+
+/// The `BitAndAssign` trait is used to specify the functionality of `&=`.
+///
+/// # Examples
+///
+/// A trivial implementation of `BitAndAssign`. When `Foo &= Foo` happens, it ends up
+/// calling `bitand_assign`, and therefore, `main` prints `Bitwise And-ing!`.
+///
+/// ```
+/// #![feature(augmented_assignments)]
+/// #![feature(op_assign_traits)]
+///
+/// use std::ops::BitAndAssign;
+///
+/// #[derive(Copy, Clone)]
+/// struct Foo;
+///
+/// impl BitAndAssign for Foo {
+///     fn bitand_assign(&mut self, _rhs: Foo) {
+///         println!("Bitwise And-ing!");
+///     }
+/// }
+///
+/// fn main() {
+///     let mut foo = Foo;
+///     foo &= Foo;
+/// }
+/// ```
+#[cfg(not(stage0))]
+#[lang = "bitand_assign"]
+#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+pub trait BitAndAssign<Rhs=Self> {
+    /// The method for the `&` operator
+    fn bitand_assign(&mut self, Rhs);
+}
+
+#[cfg(not(stage0))]
+macro_rules! bitand_assign_impl {
+    ($($t:ty)+) => ($(
+        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        impl BitAndAssign for $t {
+            #[inline]
+            fn bitand_assign(&mut self, other: $t) { *self &= other }
+        }
+    )+)
+}
+
+#[cfg(not(stage0))]
+bitand_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
+
+/// The `BitOrAssign` trait is used to specify the functionality of `|=`.
+///
+/// # Examples
+///
+/// A trivial implementation of `BitOrAssign`. When `Foo |= Foo` happens, it ends up
+/// calling `bitor_assign`, and therefore, `main` prints `Bitwise Or-ing!`.
+///
+/// ```
+/// #![feature(augmented_assignments)]
+/// #![feature(op_assign_traits)]
+///
+/// use std::ops::BitOrAssign;
+///
+/// #[derive(Copy, Clone)]
+/// struct Foo;
+///
+/// impl BitOrAssign for Foo {
+///     fn bitor_assign(&mut self, _rhs: Foo) {
+///         println!("Bitwise Or-ing!");
+///     }
+/// }
+///
+/// fn main() {
+///     let mut foo = Foo;
+///     foo |= Foo;
+/// }
+/// ```
+#[cfg(not(stage0))]
+#[lang = "bitor_assign"]
+#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+pub trait BitOrAssign<Rhs=Self> {
+    /// The method for the `|=` operator
+    fn bitor_assign(&mut self, Rhs);
+}
+
+#[cfg(not(stage0))]
+macro_rules! bitor_assign_impl {
+    ($($t:ty)+) => ($(
+        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        impl BitOrAssign for $t {
+            #[inline]
+            fn bitor_assign(&mut self, other: $t) { *self |= other }
+        }
+    )+)
+}
+
+#[cfg(not(stage0))]
+bitor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
+
+/// The `BitXorAssign` trait is used to specify the functionality of `^=`.
+///
+/// # Examples
+///
+/// A trivial implementation of `BitXorAssign`. When `Foo ^= Foo` happens, it ends up
+/// calling `bitxor_assign`, and therefore, `main` prints `Bitwise Xor-ing!`.
+///
+/// ```
+/// #![feature(augmented_assignments)]
+/// #![feature(op_assign_traits)]
+///
+/// use std::ops::BitXorAssign;
+///
+/// #[derive(Copy, Clone)]
+/// struct Foo;
+///
+/// impl BitXorAssign for Foo {
+///     fn bitxor_assign(&mut self, _rhs: Foo) {
+///         println!("Bitwise Xor-ing!");
+///     }
+/// }
+///
+/// fn main() {
+///     let mut foo = Foo;
+///     foo ^= Foo;
+/// }
+/// ```
+#[cfg(not(stage0))]
+#[lang = "bitxor_assign"]
+#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+pub trait BitXorAssign<Rhs=Self> {
+    /// The method for the `^=` operator
+    fn bitxor_assign(&mut self, Rhs);
+}
+
+#[cfg(not(stage0))]
+macro_rules! bitxor_assign_impl {
+    ($($t:ty)+) => ($(
+        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        impl BitXorAssign for $t {
+            #[inline]
+            fn bitxor_assign(&mut self, other: $t) { *self ^= other }
+        }
+    )+)
+}
+
+#[cfg(not(stage0))]
+bitxor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
+
+/// The `ShlAssign` trait is used to specify the functionality of `<<=`.
+///
+/// # Examples
+///
+/// A trivial implementation of `ShlAssign`. When `Foo <<= Foo` happens, it ends up
+/// calling `shl_assign`, and therefore, `main` prints `Shifting left!`.
+///
+/// ```
+/// #![feature(augmented_assignments)]
+/// #![feature(op_assign_traits)]
+///
+/// use std::ops::ShlAssign;
+///
+/// #[derive(Copy, Clone)]
+/// struct Foo;
+///
+/// impl ShlAssign<Foo> for Foo {
+///     fn shl_assign(&mut self, _rhs: Foo) {
+///         println!("Shifting left!");
+///     }
+/// }
+///
+/// fn main() {
+///     let mut foo = Foo;
+///     foo <<= Foo;
+/// }
+/// ```
+#[cfg(not(stage0))]
+#[lang = "shl_assign"]
+#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+pub trait ShlAssign<Rhs> {
+    /// The method for the `<<=` operator
+    fn shl_assign(&mut self, Rhs);
+}
+
+#[cfg(not(stage0))]
+macro_rules! shl_assign_impl {
+    ($t:ty, $f:ty) => (
+        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        impl ShlAssign<$f> for $t {
+            #[inline]
+            fn shl_assign(&mut self, other: $f) {
+                *self <<= other
+            }
+        }
+    )
+}
+
+#[cfg(not(stage0))]
+macro_rules! shl_assign_impl_all {
+    ($($t:ty)*) => ($(
+        shl_assign_impl! { $t, u8 }
+        shl_assign_impl! { $t, u16 }
+        shl_assign_impl! { $t, u32 }
+        shl_assign_impl! { $t, u64 }
+        shl_assign_impl! { $t, usize }
+
+        shl_assign_impl! { $t, i8 }
+        shl_assign_impl! { $t, i16 }
+        shl_assign_impl! { $t, i32 }
+        shl_assign_impl! { $t, i64 }
+        shl_assign_impl! { $t, isize }
+    )*)
+}
+
+#[cfg(not(stage0))]
+shl_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
+
+/// The `ShrAssign` trait is used to specify the functionality of `>>=`.
+///
+/// # Examples
+///
+/// A trivial implementation of `ShrAssign`. When `Foo >>= Foo` happens, it ends up
+/// calling `shr_assign`, and therefore, `main` prints `Shifting right!`.
+///
+/// ```
+/// #![feature(augmented_assignments)]
+/// #![feature(op_assign_traits)]
+///
+/// use std::ops::ShrAssign;
+///
+/// #[derive(Copy, Clone)]
+/// struct Foo;
+///
+/// impl ShrAssign<Foo> for Foo {
+///     fn shr_assign(&mut self, _rhs: Foo) {
+///         println!("Shifting right!");
+///     }
+/// }
+///
+/// fn main() {
+///     let mut foo = Foo;
+///     foo >>= Foo;
+/// }
+/// ```
+#[cfg(not(stage0))]
+#[lang = "shr_assign"]
+#[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+pub trait ShrAssign<Rhs=Self> {
+    /// The method for the `>>=` operator
+    fn shr_assign(&mut self, Rhs);
+}
+
+#[cfg(not(stage0))]
+macro_rules! shr_assign_impl {
+    ($t:ty, $f:ty) => (
+        #[unstable(feature = "op_assign_traits", reason = "recently added", issue = "28235")]
+        impl ShrAssign<$f> for $t {
+            #[inline]
+            fn shr_assign(&mut self, other: $f) {
+                *self >>= other
+            }
+        }
+    )
+}
+
+#[cfg(not(stage0))]
+macro_rules! shr_assign_impl_all {
+    ($($t:ty)*) => ($(
+        shr_assign_impl! { $t, u8 }
+        shr_assign_impl! { $t, u16 }
+        shr_assign_impl! { $t, u32 }
+        shr_assign_impl! { $t, u64 }
+        shr_assign_impl! { $t, usize }
+
+        shr_assign_impl! { $t, i8 }
+        shr_assign_impl! { $t, i16 }
+        shr_assign_impl! { $t, i32 }
+        shr_assign_impl! { $t, i64 }
+        shr_assign_impl! { $t, isize }
+    )*)
+}
+
+#[cfg(not(stage0))]
+shr_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
+
 /// The `Index` trait is used to specify the functionality of indexing operations
 /// like `arr[idx]` when used in an immutable context.
 ///
@@ -1100,7 +1628,7 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> {
 /// impl<T> Deref for DerefExample<T> {
 ///     type Target = T;
 ///
-///     fn deref<'a>(&'a self) -> &'a T {
+///     fn deref(&self) -> &T {
 ///         &self.value
 ///     }
 /// }
index a539ef81db89cf8cf7c19bec0a5d77470a4eb44c..8fce64bd561dc6dc134868ec0ecac1a9fe38b6c6 100644 (file)
@@ -290,6 +290,7 @@ impl<T> Option<T> {
                reason = "waiting for mut conventions",
                issue = "27776")]
     #[deprecated(since = "1.4.0", reason = "niche API, unclear of usefulness")]
+    #[allow(deprecated)]
     pub fn as_mut_slice(&mut self) -> &mut [T] {
         match *self {
             Some(ref mut x) => {
@@ -541,7 +542,7 @@ impl<T> Option<T> {
     /// ```
     /// let mut x = Some(4);
     /// match x.iter_mut().next() {
-    ///     Some(&mut ref mut v) => *v = 42,
+    ///     Some(v) => *v = 42,
     ///     None => {},
     /// }
     /// assert_eq!(x, Some(42));
@@ -694,6 +695,7 @@ impl<T> Option<T> {
     #[unstable(feature = "as_slice", reason = "unsure of the utility here",
                issue = "27776")]
     #[deprecated(since = "1.4.0", reason = "niche API, unclear of usefulness")]
+    #[allow(deprecated)]
     pub fn as_slice(&self) -> &[T] {
         match *self {
             Some(ref x) => slice::ref_slice(x),
@@ -706,7 +708,8 @@ impl<T> Option<T> {
 }
 
 impl<'a, T: Clone> Option<&'a T> {
-    /// Maps an Option<&T> to an Option<T> by cloning the contents of the Option.
+    /// Maps an `Option<&T>` to an `Option<T>` by cloning the contents of the
+    /// option.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn cloned(self) -> Option<T> {
         self.map(|t| t.clone())
index 831616293cd8fb99de8c41f2c9d7d7585209ce90..52a888d797ba922e848af5457829ba8a54c506bc 100644 (file)
 
 use clone::Clone;
 use intrinsics;
-use ops::Deref;
+use ops::{CoerceUnsized, Deref};
 use fmt;
 use hash;
 use option::Option::{self, Some, None};
-use marker::{PhantomData, Send, Sized, Sync};
+use marker::{Copy, PhantomData, Send, Sized, Sync, Unsize};
 use mem;
 use nonzero::NonZero;
 
@@ -69,7 +69,7 @@ pub const fn null<T>() -> *const T { 0 as *const T }
 pub const fn null_mut<T>() -> *mut T { 0 as *mut T }
 
 /// Swaps the values at two mutable locations of the same type, without
-/// deinitialising either. They may overlap, unlike `mem::swap` which is
+/// deinitializing either. They may overlap, unlike `mem::swap` which is
 /// otherwise equivalent.
 ///
 /// # Safety
@@ -145,9 +145,11 @@ pub unsafe fn read_and_drop<T>(dest: *mut T) -> T {
 ///
 /// # Safety
 ///
-/// Beyond accepting a raw pointer, this operation is unsafe because it does
-/// not drop the contents of `dst`. This could leak allocations or resources,
-/// so care must be taken not to overwrite an object that should be dropped.
+/// This operation is marked unsafe because it accepts a raw pointer.
+///
+/// It does not drop the contents of `dst`. This is safe, but it could leak
+/// allocations or resources, so care must be taken not to overwrite an object
+/// that should be dropped.
 ///
 /// This is appropriate for initializing uninitialized memory, or overwriting
 /// memory that has previously been `read` from.
@@ -245,7 +247,7 @@ impl<T: ?Sized> *mut T {
     /// # Safety
     ///
     /// The offset must be in-bounds of the object, or one-byte-past-the-end.
-    /// Otherwise `offset` invokes Undefined Behaviour, regardless of whether
+    /// Otherwise `offset` invokes Undefined Behavior, regardless of whether
     /// the pointer is used.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -496,12 +498,28 @@ unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
 #[unstable(feature = "unique", issue = "27730")]
 unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
 
+#[cfg(stage0)]
+macro_rules! unique_new {
+    () => (
+        /// Creates a new `Unique`.
+        pub unsafe fn new(ptr: *mut T) -> Unique<T> {
+            Unique { pointer: NonZero::new(ptr), _marker: PhantomData }
+        }
+    )
+}
+#[cfg(not(stage0))]
+macro_rules! unique_new {
+    () => (
+        /// Creates a new `Unique`.
+        pub const unsafe fn new(ptr: *mut T) -> Unique<T> {
+            Unique { pointer: NonZero::new(ptr), _marker: PhantomData }
+        }
+    )
+}
+
 #[unstable(feature = "unique", issue = "27730")]
 impl<T: ?Sized> Unique<T> {
-    /// Creates a new `Unique`.
-    pub unsafe fn new(ptr: *mut T) -> Unique<T> {
-        Unique { pointer: NonZero::new(ptr), _marker: PhantomData }
-    }
+    unique_new!{}
 
     /// Dereferences the content.
     pub unsafe fn get(&self) -> &T {
@@ -530,3 +548,68 @@ impl<T> fmt::Pointer for Unique<T> {
         fmt::Pointer::fmt(&*self.pointer, f)
     }
 }
+
+/// A wrapper around a raw `*mut T` that indicates that the possessor
+/// of this wrapper has shared ownership of the referent. Useful for
+/// building abstractions like `Rc<T>` or `Arc<T>`, which internally
+/// use raw pointers to manage the memory that they own.
+#[unstable(feature = "shared", reason = "needs an RFC to flesh out design",
+           issue = "27730")]
+pub struct Shared<T: ?Sized> {
+    pointer: NonZero<*const T>,
+    // NOTE: this marker has no consequences for variance, but is necessary
+    // for dropck to understand that we logically own a `T`.
+    //
+    // For details, see:
+    // https://github.com/rust-lang/rfcs/blob/master/text/0769-sound-generic-drop.md#phantom-data
+    _marker: PhantomData<T>,
+}
+
+/// `Shared` pointers are not `Send` because the data they reference may be aliased.
+// NB: This impl is unnecessary, but should provide better error messages.
+#[unstable(feature = "shared", issue = "27730")]
+impl<T: ?Sized> !Send for Shared<T> { }
+
+/// `Shared` pointers are not `Sync` because the data they reference may be aliased.
+// NB: This impl is unnecessary, but should provide better error messages.
+#[unstable(feature = "shared", issue = "27730")]
+impl<T: ?Sized> !Sync for Shared<T> { }
+
+#[unstable(feature = "shared", issue = "27730")]
+impl<T: ?Sized> Shared<T> {
+    /// Creates a new `Shared`.
+    pub unsafe fn new(ptr: *mut T) -> Self {
+        Shared { pointer: NonZero::new(ptr), _marker: PhantomData }
+    }
+}
+
+#[unstable(feature = "shared", issue = "27730")]
+impl<T: ?Sized> Clone for Shared<T> {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
+#[unstable(feature = "shared", issue = "27730")]
+impl<T: ?Sized> Copy for Shared<T> { }
+
+#[cfg(not(stage0))] // remove cfg after new snapshot
+#[unstable(feature = "shared", issue = "27730")]
+impl<T: ?Sized, U: ?Sized> CoerceUnsized<Shared<U>> for Shared<T> where T: Unsize<U> { }
+
+#[unstable(feature = "shared", issue = "27730")]
+impl<T: ?Sized> Deref for Shared<T> {
+    type Target = *mut T;
+
+    #[inline]
+    fn deref(&self) -> &*mut T {
+        unsafe { mem::transmute(&*self.pointer) }
+    }
+}
+
+#[unstable(feature = "shared", issue = "27730")]
+impl<T> fmt::Pointer for Shared<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Pointer::fmt(&*self.pointer, f)
+    }
+}
index 382fd0f3788ced524be6e66de1ae874ecb0997b6..84467be6eca5641d30e15a0a4240fc827b761ec1 100644 (file)
@@ -94,7 +94,7 @@ impl<T> Clone for Slice<T> {
 /// Synthesizing a trait object with mismatched types—one where the
 /// vtable does not correspond to the type of the value to which the
 /// data pointer points—is highly likely to lead to undefined
-/// behaviour.
+/// behavior.
 ///
 /// # Examples
 ///
index e9a67196751e00f2e6eec7328ccc236133223c97..e48252fa6f62a0a40d403484578658bf4985c544 100644 (file)
@@ -408,6 +408,7 @@ impl<T, E> Result<T, E> {
     #[unstable(feature = "as_slice", reason = "unsure of the utility here",
                issue = "27776")]
     #[deprecated(since = "1.4.0", reason = "niche API, unclear of usefulness")]
+    #[allow(deprecated)]
     pub fn as_slice(&self) -> &[T] {
         match *self {
             Ok(ref x) => slice::ref_slice(x),
@@ -441,6 +442,7 @@ impl<T, E> Result<T, E> {
                reason = "waiting for mut conventions",
                issue = "27776")]
     #[deprecated(since = "1.4.0", reason = "niche API, unclear of usefulness")]
+    #[allow(deprecated)]
     pub fn as_mut_slice(&mut self) -> &mut [T] {
         match *self {
             Ok(ref mut x) => slice::mut_ref_slice(x),
@@ -538,7 +540,7 @@ impl<T, E> Result<T, E> {
     /// ```
     /// let mut x: Result<u32, &str> = Ok(7);
     /// match x.iter_mut().next() {
-    ///     Some(&mut ref mut x) => *x = 40,
+    ///     Some(v) => *v = 40,
     ///     None => {},
     /// }
     /// assert_eq!(x, Ok(40));
index 8d3d798afef131215c71fdff08e0c9bad16844e1..a49d91ca03e5b353fb6df83a5a79f248e4b644aa 100644 (file)
@@ -655,6 +655,11 @@ impl<'a, T> Default for &'a [T] {
     fn default() -> &'a [T] { &[] }
 }
 
+#[stable(feature = "mut_slice_default", since = "1.5.0")]
+impl<'a, T> Default for &'a mut [T] {
+    fn default() -> &'a mut [T] { &mut [] }
+}
+
 //
 // Iterators
 //
@@ -1410,16 +1415,18 @@ impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {}
 // Free functions
 //
 
-/// Converts a pointer to A into a slice of length 1 (without copying).
+/// Converts a reference to A into a slice of length 1 (without copying).
 #[unstable(feature = "ref_slice", issue = "27774")]
+#[deprecated(since = "1.5.0", reason = "unclear whether belongs in libstd")]
 pub fn ref_slice<A>(s: &A) -> &[A] {
     unsafe {
         from_raw_parts(s, 1)
     }
 }
 
-/// Converts a pointer to A into a slice of length 1 (without copying).
+/// Converts a reference to A into a slice of length 1 (without copying).
 #[unstable(feature = "ref_slice", issue = "27774")]
+#[deprecated(since = "1.5.0", reason = "unclear whether belongs in libstd")]
 pub fn mut_ref_slice<A>(s: &mut A) -> &mut [A] {
     unsafe {
         from_raw_parts_mut(s, 1)
@@ -1430,7 +1437,7 @@ pub fn mut_ref_slice<A>(s: &mut A) -> &mut [A] {
 ///
 /// The `len` argument is the number of **elements**, not the number of bytes.
 ///
-/// # Unsafety
+/// # Safety
 ///
 /// This function is unsafe as there is no guarantee that the given pointer is
 /// valid for `len` elements, nor whether the lifetime inferred is a suitable
@@ -1559,30 +1566,41 @@ impl<T: Eq> Eq for [T] {}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> Ord for [T] {
     fn cmp(&self, other: &[T]) -> Ordering {
-        self.iter().cmp(other.iter())
+        let l = cmp::min(self.len(), other.len());
+
+        // Slice to the loop iteration range to enable bound check
+        // elimination in the compiler
+        let lhs = &self[..l];
+        let rhs = &other[..l];
+
+        for i in 0..l {
+            match lhs[i].cmp(&rhs[i]) {
+                Ordering::Equal => (),
+                non_eq => return non_eq,
+            }
+        }
+
+        self.len().cmp(&other.len())
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: PartialOrd> PartialOrd for [T] {
-    #[inline]
     fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
-        self.iter().partial_cmp(other.iter())
-    }
-    #[inline]
-    fn lt(&self, other: &[T]) -> bool {
-        self.iter().lt(other.iter())
-    }
-    #[inline]
-    fn le(&self, other: &[T]) -> bool {
-        self.iter().le(other.iter())
-    }
-    #[inline]
-    fn ge(&self, other: &[T]) -> bool {
-        self.iter().ge(other.iter())
-    }
-    #[inline]
-    fn gt(&self, other: &[T]) -> bool {
-        self.iter().gt(other.iter())
+        let l = cmp::min(self.len(), other.len());
+
+        // Slice to the loop iteration range to enable bound check
+        // elimination in the compiler
+        let lhs = &self[..l];
+        let rhs = &other[..l];
+
+        for i in 0..l {
+            match lhs[i].partial_cmp(&rhs[i]) {
+                Some(Ordering::Equal) => (),
+                non_eq => return non_eq,
+            }
+        }
+
+        self.len().partial_cmp(&other.len())
     }
 }
index 69ebcb1ab7e14928ed96f3f24b43460a5d522343..7a78460a841bd1cab81aff200b149c21a6dcb99f 100644 (file)
@@ -48,6 +48,21 @@ pub trait FromStr: Sized {
     /// If parsing succeeds, return the value inside `Ok`, otherwise
     /// when the string is ill-formatted return an error specific to the
     /// inside `Err`. The error type is specific to implementation of the trait.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage with [`i32`][ithirtytwo], a type that implements `FromStr`:
+    ///
+    /// [ithirtytwo]: ../primitive.i32.html
+    ///
+    /// ```
+    /// use std::str::FromStr;
+    ///
+    /// let s = "5";
+    /// let x = i32::from_str(s).unwrap();
+    ///
+    /// assert_eq!(5, x);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn from_str(s: &str) -> Result<Self, Self::Err>;
 }
@@ -104,7 +119,11 @@ impl fmt::Display for ParseBoolError {
 Section: Creating a string
 */
 
-/// Errors which can occur when attempting to interpret a byte slice as a `str`.
+/// Errors which can occur when attempting to interpret a sequence of `u8`
+/// as a string.
+///
+/// As such, the `from_utf8` family of functions and methods for both `String`s
+/// and `&str`s make use of this error, for example.
 #[derive(Copy, Eq, PartialEq, Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Utf8Error {
@@ -115,23 +134,105 @@ impl Utf8Error {
     /// Returns the index in the given string up to which valid UTF-8 was
     /// verified.
     ///
-    /// Starting at the index provided, but not necessarily at it precisely, an
-    /// invalid UTF-8 encoding sequence was found.
-    #[unstable(feature = "utf8_error", reason = "method just added",
-               issue = "27734")]
+    /// It is the maximum index such that `from_utf8(input[..index])`
+    /// would return `Some(_)`.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(utf8_error)]
+    ///
+    /// use std::str;
+    ///
+    /// // some invalid bytes, in a vector
+    /// let sparkle_heart = vec![0, 159, 146, 150];
+    ///
+    /// // std::str::from_utf8 returns a Utf8Error
+    /// let error = str::from_utf8(&sparkle_heart).unwrap_err();
+    ///
+    /// // the first byte is invalid here
+    /// assert_eq!(1, error.valid_up_to());
+    /// ```
+    #[stable(feature = "utf8_error", since = "1.5.0")]
     pub fn valid_up_to(&self) -> usize { self.valid_up_to }
 }
 
-/// Converts a slice of bytes to a string slice without performing any
-/// allocations.
+/// Converts a slice of bytes to a string slice.
 ///
-/// Once the slice has been validated as UTF-8, it is transmuted in-place and
-/// returned as a '&str' instead of a '&[u8]'
+/// A string slice (`&str`) is made of bytes (`u8`), and a byte slice (`&[u8]`)
+/// is made of bytes, so this function converts between the two. Not all byte
+/// slices are valid string slices, however: `&str` requires that it is valid
+/// UTF-8. `from_utf8()` checks to ensure that the bytes are valid UTF-8, and
+/// then does the conversion.
+///
+/// If you are sure that the byte slice is valid UTF-8, and you don't want to
+/// incur the overhead of the validity check, there is an unsafe version of
+/// this function, [`from_utf8_unchecked()`][fromutf8], which has the same
+/// behavior but skips the check.
+///
+/// [fromutf8]: fn.from_utf8.html
+///
+/// If you need a `String` instead of a `&str`, consider
+/// [`String::from_utf8()`][string].
+///
+/// [string]: ../string/struct.String.html#method.from_utf8
+///
+/// Because you can stack-allocate a `[u8; N]`, and you can take a `&[u8]` of
+/// it, this function is one way to have a stack-allocated string. There is
+/// an example of this in the examples section below.
 ///
 /// # Failure
 ///
 /// Returns `Err` if the slice is not UTF-8 with a description as to why the
 /// provided slice is not UTF-8.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::str;
+///
+/// // some bytes, in a vector
+/// let sparkle_heart = vec![240, 159, 146, 150];
+///
+/// // We know these bytes are valid, so just use `unwrap()`.
+/// let sparkle_heart = str::from_utf8(&sparkle_heart).unwrap();
+///
+/// assert_eq!("💖", sparkle_heart);
+/// ```
+///
+/// Incorrect bytes:
+///
+/// ```
+/// use std::str;
+///
+/// // some invalid bytes, in a vector
+/// let sparkle_heart = vec![0, 159, 146, 150];
+///
+/// assert!(str::from_utf8(&sparkle_heart).is_err());
+/// ```
+///
+/// See the docs for [`Utf8Error`][error] for more details on the kinds of
+/// errors that can be returned.
+///
+/// [error]: struct.Utf8Error.html
+///
+/// A "stack allocated string":
+///
+/// ```
+/// use std::str;
+///
+/// // some bytes, in a stack-allocated array
+/// let sparkle_heart = [240, 159, 146, 150];
+///
+/// // We know these bytes are valid, so just use `unwrap()`.
+/// let sparkle_heart = str::from_utf8(&sparkle_heart).unwrap();
+///
+/// assert_eq!("💖", sparkle_heart);
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
     try!(run_utf8_validation_iterator(&mut v.iter()));
@@ -140,6 +241,33 @@ pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
 
 /// Converts a slice of bytes to a string slice without checking
 /// that the string contains valid UTF-8.
+///
+/// See the safe version, [`from_utf8()`][fromutf8], for more.
+///
+/// [fromutf8]: fn.from_utf8.html
+///
+/// # Safety
+///
+/// This function is unsafe because it does not check that the bytes passed to
+/// it are valid UTF-8. If this constraint is violated, undefined behavior
+/// results, as the rest of Rust assumes that `&str`s are valid UTF-8.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::str;
+///
+/// // some bytes, in a vector
+/// let sparkle_heart = vec![240, 159, 146, 150];
+///
+/// let sparkle_heart = unsafe {
+///     str::from_utf8_unchecked(&sparkle_heart)
+/// };
+///
+/// assert_eq!("💖", sparkle_heart);
+/// ```
 #[inline(always)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
@@ -433,7 +561,7 @@ macro_rules! derive_pattern_clone {
 }
 
 /// This macro generates two public iterator structs
-/// wrapping an private internal one that makes use of the `Pattern` API.
+/// wrapping a private internal one that makes use of the `Pattern` API.
 ///
 /// For all patterns `P: Pattern<'a>` the following items will be
 /// generated (generics omitted):
@@ -729,15 +857,19 @@ struct MatchIndicesInternal<'a, P: Pattern<'a>>(P::Searcher);
 
 impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> {
     #[inline]
-    fn next(&mut self) -> Option<(usize, usize)> {
-        self.0.next_match()
+    fn next(&mut self) -> Option<(usize, &'a str)> {
+        self.0.next_match().map(|(start, end)| unsafe {
+            (start, self.0.haystack().slice_unchecked(start, end))
+        })
     }
 
     #[inline]
-    fn next_back(&mut self) -> Option<(usize, usize)>
+    fn next_back(&mut self) -> Option<(usize, &'a str)>
         where P::Searcher: ReverseSearcher<'a>
     {
-        self.0.next_match_back()
+        self.0.next_match_back().map(|(start, end)| unsafe {
+            (start, self.0.haystack().slice_unchecked(start, end))
+        })
     }
 }
 
@@ -749,11 +881,9 @@ generate_pattern_iterators! {
         /// Created with the method `.rmatch_indices()`.
         struct RMatchIndices;
     stability:
-        #[unstable(feature = "str_match_indices",
-                   reason = "type may be removed or have its iterator impl changed",
-                   issue = "27743")]
+        #[stable(feature = "str_match_indices", since = "1.5.0")]
     internal:
-        MatchIndicesInternal yielding ((usize, usize));
+        MatchIndicesInternal yielding ((usize, &'a str));
     delegate double ended;
 }
 
@@ -832,7 +962,7 @@ impl<'a> DoubleEndedIterator for Lines<'a> {
 #[allow(deprecated)]
 pub struct LinesAny<'a>(Lines<'a>);
 
-/// A nameable, clonable fn type
+/// A nameable, cloneable fn type
 #[derive(Clone)]
 struct LinesAnyMap;
 
index 53952cdc9080b525a1f9514994d42848a22908d6..7225b4f6e0d2abbdcfb6154f5ecb2978c16e4cdd 100644 (file)
@@ -92,6 +92,7 @@ impl Default for AtomicBool {
     }
 }
 
+// Send is implicitly implemented for AtomicBool.
 unsafe impl Sync for AtomicBool {}
 
 /// A signed integer type which can be safely shared between threads.
@@ -106,6 +107,7 @@ impl Default for AtomicIsize {
     }
 }
 
+// Send is implicitly implemented for AtomicIsize.
 unsafe impl Sync for AtomicIsize {}
 
 /// An unsigned integer type which can be safely shared between threads.
@@ -120,6 +122,7 @@ impl Default for AtomicUsize {
     }
 }
 
+// Send is implicitly implemented for AtomicUsize.
 unsafe impl Sync for AtomicUsize {}
 
 /// A raw pointer type which can be safely shared between threads.
@@ -150,7 +153,8 @@ unsafe impl<T> Sync for AtomicPtr<T> {}
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Copy, Clone)]
 pub enum Ordering {
-    /// No ordering constraints, only atomic operations.
+    /// No ordering constraints, only atomic operations. Corresponds to LLVM's
+    /// `Monotonic` ordering.
     #[stable(feature = "rust1", since = "1.0.0")]
     Relaxed,
     /// When coupled with a store, all previous writes become visible
index 20740a5e2cebc91dc3649cbf6a2c60536c4efe2e..309a3d51c7602856c4d59f8dc2a4b9d6702463da 100644 (file)
@@ -248,15 +248,14 @@ fn unsafe_cell_unsized() {
     assert_eq!(unsafe { &mut *cell.get() }, comp);
 }
 
-// FIXME(#25351) needs deeply nested coercions of DST structs.
-// #[test]
-// fn refcell_unsized() {
-//     let cell: &RefCell<[i32]> = &RefCell::new([1, 2, 3]);
-//     {
-//         let b = &mut *cell.borrow_mut();
-//         b[0] = 4;
-//         b[2] = 5;
-//     }
-//     let comp: &mut [i32] = &mut [4, 2, 5];
-//     assert_eq!(&*cell.borrow(), comp);
-// }
+#[test]
+fn refcell_unsized() {
+    let cell: &RefCell<[i32]> = &RefCell::new([1, 2, 3]);
+    {
+        let b = &mut *cell.borrow_mut();
+        b[0] = 4;
+        b[2] = 5;
+    }
+    let comp: &mut [i32] = &mut [4, 2, 5];
+    assert_eq!(&*cell.borrow(), comp);
+}
index 5ab6ab27ba1d0680170d2ae9fa33cd9a4787e9b2..91d68ba33447aa99115bd3491a932a625f8315b7 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -11,8 +11,8 @@
 #[test]
 fn test_borrowed_clone() {
     let x = 5;
-    let y: &int = &x;
-    let z: &int = (&y).clone();
+    let y: &i32 = &x;
+    let z: &i32 = (&y).clone();
     assert_eq!(*z, 5);
 }
 
@@ -23,17 +23,3 @@ fn test_clone_from() {
     b.clone_from(&a);
     assert_eq!(*b, 5);
 }
-
-#[test]
-fn test_extern_fn_clone() {
-    trait Empty {}
-    impl Empty for int {}
-
-    fn test_fn_a() -> f64 { 1.0 }
-    fn test_fn_b<T: Empty>(x: T) -> T { x }
-    fn test_fn_c(_: int, _: f64, _: int, _: int, _: int) {}
-
-    let _ = test_fn_a.clone();
-    let _ = test_fn_b::<int>.clone();
-    let _ = test_fn_c.clone();
-}
index 6b14fa8be8eef5d553d54cf6cdd2755ef405ce95..16cd2feddc0b8e624bb0c1230a75e6f9673681b6 100644 (file)
@@ -13,5 +13,7 @@ fn test_format_float() {
     assert!("1" == format!("{:.0}", 1.0f64));
     assert!("9" == format!("{:.0}", 9.4f64));
     assert!("10" == format!("{:.0}", 9.9f64));
-    assert!("9.9" == format!("{:.1}", 9.85f64));
+    assert!("9.8" == format!("{:.1}", 9.849f64));
+    assert!("9.9" == format!("{:.1}", 9.851f64));
+    assert!("1" == format!("{:.0}", 0.5f64));
 }
index 42872589bb01fa296dbe0d76ffb8e2575a6ef5e7..99ea39c619f77ca5ab208c30603028b6f19bdfea 100644 (file)
@@ -8,8 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-mod num;
 mod builders;
+mod float;
+mod num;
 
 #[test]
 fn test_format_flags() {
index c99fb8c197d834bb7815910085b729cf2870777f..2b380abf63c58dddab364dcb64be682279d9df87 100644 (file)
@@ -12,7 +12,7 @@ use core::any::TypeId;
 
 #[test]
 fn test_typeid_sized_types() {
-    struct X; struct Y(uint);
+    struct X; struct Y(u32);
 
     assert_eq!(TypeId::of::<X>(), TypeId::of::<X>());
     assert_eq!(TypeId::of::<Y>(), TypeId::of::<Y>());
index e87a179f58d144f8db7f98e4c2602e2184dc9342..96886c9104876b0790e5820cb2ee188bc1b42f1f 100644 (file)
@@ -15,6 +15,8 @@
 #![feature(const_fn)]
 #![feature(core)]
 #![feature(core_float)]
+#![feature(core_private_bignum)]
+#![feature(core_private_diy_float)]
 #![feature(dec2flt)]
 #![feature(decode_utf16)]
 #![feature(fixed_size_array)]
@@ -52,9 +54,11 @@ mod array;
 mod atomic;
 mod cell;
 mod char;
+mod clone;
 mod cmp;
 mod fmt;
 mod hash;
+mod intrinsics;
 mod iter;
 mod mem;
 mod nonzero;
diff --git a/src/libcoretest/num/bignum.rs b/src/libcoretest/num/bignum.rs
new file mode 100644 (file)
index 0000000..58a9dd1
--- /dev/null
@@ -0,0 +1,249 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::prelude::v1::*;
+use core::num::bignum::tests::Big8x3 as Big;
+
+#[test]
+#[should_panic]
+fn test_from_u64_overflow() {
+    Big::from_u64(0x1000000);
+}
+
+#[test]
+fn test_add() {
+    assert_eq!(*Big::from_small(3).add(&Big::from_small(4)), Big::from_small(7));
+    assert_eq!(*Big::from_small(3).add(&Big::from_small(0)), Big::from_small(3));
+    assert_eq!(*Big::from_small(0).add(&Big::from_small(3)), Big::from_small(3));
+    assert_eq!(*Big::from_small(3).add(&Big::from_u64(0xfffe)), Big::from_u64(0x10001));
+    assert_eq!(*Big::from_u64(0xfedc).add(&Big::from_u64(0x789)), Big::from_u64(0x10665));
+    assert_eq!(*Big::from_u64(0x789).add(&Big::from_u64(0xfedc)), Big::from_u64(0x10665));
+}
+
+#[test]
+#[should_panic]
+fn test_add_overflow_1() {
+    Big::from_small(1).add(&Big::from_u64(0xffffff));
+}
+
+#[test]
+#[should_panic]
+fn test_add_overflow_2() {
+    Big::from_u64(0xffffff).add(&Big::from_small(1));
+}
+
+#[test]
+fn test_add_small() {
+    assert_eq!(*Big::from_small(3).add_small(4), Big::from_small(7));
+    assert_eq!(*Big::from_small(3).add_small(0), Big::from_small(3));
+    assert_eq!(*Big::from_small(0).add_small(3), Big::from_small(3));
+    assert_eq!(*Big::from_small(7).add_small(250), Big::from_u64(257));
+    assert_eq!(*Big::from_u64(0x7fff).add_small(1), Big::from_u64(0x8000));
+    assert_eq!(*Big::from_u64(0x2ffe).add_small(0x35), Big::from_u64(0x3033));
+    assert_eq!(*Big::from_small(0xdc).add_small(0x89), Big::from_u64(0x165));
+}
+
+#[test]
+#[should_panic]
+fn test_add_small_overflow() {
+    Big::from_u64(0xffffff).add_small(1);
+}
+
+#[test]
+fn test_sub() {
+    assert_eq!(*Big::from_small(7).sub(&Big::from_small(4)), Big::from_small(3));
+    assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x789)), Big::from_u64(0xfedc));
+    assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0xfedc)), Big::from_u64(0x789));
+    assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x10664)), Big::from_small(1));
+    assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x10665)), Big::from_small(0));
+}
+
+#[test]
+#[should_panic]
+fn test_sub_underflow_1() {
+    Big::from_u64(0x10665).sub(&Big::from_u64(0x10666));
+}
+
+#[test]
+#[should_panic]
+fn test_sub_underflow_2() {
+    Big::from_small(0).sub(&Big::from_u64(0x123456));
+}
+
+#[test]
+fn test_mul_small() {
+    assert_eq!(*Big::from_small(7).mul_small(5), Big::from_small(35));
+    assert_eq!(*Big::from_small(0xff).mul_small(0xff), Big::from_u64(0xfe01));
+    assert_eq!(*Big::from_u64(0xffffff/13).mul_small(13), Big::from_u64(0xffffff));
+}
+
+#[test]
+#[should_panic]
+fn test_mul_small_overflow() {
+    Big::from_u64(0x800000).mul_small(2);
+}
+
+#[test]
+fn test_mul_pow2() {
+    assert_eq!(*Big::from_small(0x7).mul_pow2(4), Big::from_small(0x70));
+    assert_eq!(*Big::from_small(0xff).mul_pow2(1), Big::from_u64(0x1fe));
+    assert_eq!(*Big::from_small(0xff).mul_pow2(12), Big::from_u64(0xff000));
+    assert_eq!(*Big::from_small(0x1).mul_pow2(23), Big::from_u64(0x800000));
+    assert_eq!(*Big::from_u64(0x123).mul_pow2(0), Big::from_u64(0x123));
+    assert_eq!(*Big::from_u64(0x123).mul_pow2(7), Big::from_u64(0x9180));
+    assert_eq!(*Big::from_u64(0x123).mul_pow2(15), Big::from_u64(0x918000));
+    assert_eq!(*Big::from_small(0).mul_pow2(23), Big::from_small(0));
+}
+
+#[test]
+#[should_panic]
+fn test_mul_pow2_overflow_1() {
+    Big::from_u64(0x1).mul_pow2(24);
+}
+
+#[test]
+#[should_panic]
+fn test_mul_pow2_overflow_2() {
+    Big::from_u64(0x123).mul_pow2(16);
+}
+
+#[test]
+fn test_mul_pow5() {
+    assert_eq!(*Big::from_small(42).mul_pow5(0), Big::from_small(42));
+    assert_eq!(*Big::from_small(1).mul_pow5(2), Big::from_small(25));
+    assert_eq!(*Big::from_small(1).mul_pow5(4), Big::from_u64(25 * 25));
+    assert_eq!(*Big::from_small(4).mul_pow5(3), Big::from_u64(500));
+    assert_eq!(*Big::from_small(140).mul_pow5(2), Big::from_u64(25 * 140));
+    assert_eq!(*Big::from_small(25).mul_pow5(1), Big::from_small(125));
+    assert_eq!(*Big::from_small(125).mul_pow5(7), Big::from_u64(9765625));
+    assert_eq!(*Big::from_small(0).mul_pow5(127), Big::from_small(0));
+}
+
+#[test]
+#[should_panic]
+fn test_mul_pow5_overflow_1() {
+    Big::from_small(1).mul_pow5(12);
+}
+
+#[test]
+#[should_panic]
+fn test_mul_pow5_overflow_2() {
+    Big::from_small(230).mul_pow5(8);
+}
+
+#[test]
+fn test_mul_digits() {
+    assert_eq!(*Big::from_small(3).mul_digits(&[5]), Big::from_small(15));
+    assert_eq!(*Big::from_small(0xff).mul_digits(&[0xff]), Big::from_u64(0xfe01));
+    assert_eq!(*Big::from_u64(0x123).mul_digits(&[0x56, 0x4]), Big::from_u64(0x4edc2));
+    assert_eq!(*Big::from_u64(0x12345).mul_digits(&[0x67]), Big::from_u64(0x7530c3));
+    assert_eq!(*Big::from_small(0x12).mul_digits(&[0x67, 0x45, 0x3]), Big::from_u64(0x3ae13e));
+    assert_eq!(*Big::from_u64(0xffffff/13).mul_digits(&[13]), Big::from_u64(0xffffff));
+    assert_eq!(*Big::from_small(13).mul_digits(&[0x3b, 0xb1, 0x13]), Big::from_u64(0xffffff));
+}
+
+#[test]
+#[should_panic]
+fn test_mul_digits_overflow_1() {
+    Big::from_u64(0x800000).mul_digits(&[2]);
+}
+
+#[test]
+#[should_panic]
+fn test_mul_digits_overflow_2() {
+    Big::from_u64(0x1000).mul_digits(&[0, 0x10]);
+}
+
+#[test]
+fn test_div_rem_small() {
+    let as_val = |(q, r): (&mut Big, u8)| (q.clone(), r);
+    assert_eq!(as_val(Big::from_small(0xff).div_rem_small(15)), (Big::from_small(17), 0));
+    assert_eq!(as_val(Big::from_small(0xff).div_rem_small(16)), (Big::from_small(15), 15));
+    assert_eq!(as_val(Big::from_small(3).div_rem_small(40)), (Big::from_small(0), 3));
+    assert_eq!(as_val(Big::from_u64(0xffffff).div_rem_small(123)),
+               (Big::from_u64(0xffffff / 123), (0xffffffu64 % 123) as u8));
+    assert_eq!(as_val(Big::from_u64(0x10000).div_rem_small(123)),
+               (Big::from_u64(0x10000 / 123), (0x10000u64 % 123) as u8));
+}
+
+#[test]
+fn test_div_rem() {
+    fn div_rem(n: u64, d: u64) -> (Big, Big) {
+        let mut q = Big::from_small(42);
+        let mut r = Big::from_small(42);
+        Big::from_u64(n).div_rem(&Big::from_u64(d), &mut q, &mut r);
+        (q, r)
+    }
+    assert_eq!(div_rem(1, 1), (Big::from_small(1), Big::from_small(0)));
+    assert_eq!(div_rem(4, 3), (Big::from_small(1), Big::from_small(1)));
+    assert_eq!(div_rem(1, 7), (Big::from_small(0), Big::from_small(1)));
+    assert_eq!(div_rem(45, 9), (Big::from_small(5), Big::from_small(0)));
+    assert_eq!(div_rem(103, 9), (Big::from_small(11), Big::from_small(4)));
+    assert_eq!(div_rem(123456, 77), (Big::from_u64(1603), Big::from_small(25)));
+    assert_eq!(div_rem(0xffff, 1), (Big::from_u64(0xffff), Big::from_small(0)));
+    assert_eq!(div_rem(0xeeee, 0xffff), (Big::from_small(0), Big::from_u64(0xeeee)));
+    assert_eq!(div_rem(2_000_000, 2), (Big::from_u64(1_000_000), Big::from_u64(0)));
+}
+
+#[test]
+fn test_is_zero() {
+    assert!(Big::from_small(0).is_zero());
+    assert!(!Big::from_small(3).is_zero());
+    assert!(!Big::from_u64(0x123).is_zero());
+    assert!(!Big::from_u64(0xffffff).sub(&Big::from_u64(0xfffffe)).is_zero());
+    assert!(Big::from_u64(0xffffff).sub(&Big::from_u64(0xffffff)).is_zero());
+}
+
+#[test]
+fn test_get_bit() {
+    let x = Big::from_small(0b1101);
+    assert_eq!(x.get_bit(0), 1);
+    assert_eq!(x.get_bit(1), 0);
+    assert_eq!(x.get_bit(2), 1);
+    assert_eq!(x.get_bit(3), 1);
+    let y = Big::from_u64(1 << 15);
+    assert_eq!(y.get_bit(14), 0);
+    assert_eq!(y.get_bit(15), 1);
+    assert_eq!(y.get_bit(16), 0);
+}
+
+#[test]
+#[should_panic]
+fn test_get_bit_out_of_range() {
+    Big::from_small(42).get_bit(24);
+}
+
+#[test]
+fn test_bit_length() {
+    assert_eq!(Big::from_small(0).bit_length(), 0);
+    assert_eq!(Big::from_small(1).bit_length(), 1);
+    assert_eq!(Big::from_small(5).bit_length(), 3);
+    assert_eq!(Big::from_small(0x18).bit_length(), 5);
+    assert_eq!(Big::from_u64(0x4073).bit_length(), 15);
+    assert_eq!(Big::from_u64(0xffffff).bit_length(), 24);
+}
+
+#[test]
+fn test_ord() {
+    assert!(Big::from_u64(0) < Big::from_u64(0xffffff));
+    assert!(Big::from_u64(0x102) < Big::from_u64(0x201));
+}
+
+#[test]
+fn test_fmt() {
+    assert_eq!(format!("{:?}", Big::from_u64(0)), "0x0");
+    assert_eq!(format!("{:?}", Big::from_u64(0x1)), "0x1");
+    assert_eq!(format!("{:?}", Big::from_u64(0x12)), "0x12");
+    assert_eq!(format!("{:?}", Big::from_u64(0x123)), "0x1_23");
+    assert_eq!(format!("{:?}", Big::from_u64(0x1234)), "0x12_34");
+    assert_eq!(format!("{:?}", Big::from_u64(0x12345)), "0x1_23_45");
+    assert_eq!(format!("{:?}", Big::from_u64(0x123456)), "0x12_34_56");
+}
+
index fb98e7e6f9adf8676fb8f9af8e0e686483750668..0c92b2fe2a7dc425de69110c586b98daf62c14d3 100644 (file)
@@ -16,7 +16,7 @@ use test;
 mod parse;
 mod rawfp;
 
-// Take an float literal, turn it into a string in various ways (that are all trusted
+// Take a float literal, turn it into a string in various ways (that are all trusted
 // to be correct) and see if those strings are parsed back to the value of the literal.
 // Requires a *polymorphic literal*, i.e. one that can serve as f64 as well as f32.
 macro_rules! test_literal {
index a40d360f1054a0ef17b6180e78df2cf3968e3dea..4c0a403e574a3c1a2e312b4f61053aa9c1793b3c 100644 (file)
@@ -9,14 +9,14 @@
 // except according to those terms.
 
 use std::f64;
-use core::num::flt2dec::strategy::grisu::Fp;
+use core::num::diy_float::Fp;
 use core::num::dec2flt::rawfp::{fp_to_float, prev_float, next_float, round_normal};
 
 #[test]
 fn fp_to_float_half_to_even() {
     fn is_normalized(sig: u64) -> bool {
-            // intentionally written without {min,max}_sig() as a sanity check
-            sig >> 52 == 1 && sig >> 53 == 0
+        // intentionally written without {min,max}_sig() as a sanity check
+        sig >> 52 == 1 && sig >> 53 == 0
     }
 
     fn conv(sig: u64) -> u64 {
diff --git a/src/libcoretest/num/flt2dec/bignum.rs b/src/libcoretest/num/flt2dec/bignum.rs
deleted file mode 100644 (file)
index 31065b2..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::prelude::v1::*;
-use core::num::flt2dec::bignum::tests::Big8x3 as Big;
-
-#[test]
-#[should_panic]
-fn test_from_u64_overflow() {
-    Big::from_u64(0x1000000);
-}
-
-#[test]
-fn test_add() {
-    assert_eq!(*Big::from_small(3).add(&Big::from_small(4)), Big::from_small(7));
-    assert_eq!(*Big::from_small(3).add(&Big::from_small(0)), Big::from_small(3));
-    assert_eq!(*Big::from_small(0).add(&Big::from_small(3)), Big::from_small(3));
-    assert_eq!(*Big::from_small(3).add(&Big::from_u64(0xfffe)), Big::from_u64(0x10001));
-    assert_eq!(*Big::from_u64(0xfedc).add(&Big::from_u64(0x789)), Big::from_u64(0x10665));
-    assert_eq!(*Big::from_u64(0x789).add(&Big::from_u64(0xfedc)), Big::from_u64(0x10665));
-}
-
-#[test]
-#[should_panic]
-fn test_add_overflow_1() {
-    Big::from_small(1).add(&Big::from_u64(0xffffff));
-}
-
-#[test]
-#[should_panic]
-fn test_add_overflow_2() {
-    Big::from_u64(0xffffff).add(&Big::from_small(1));
-}
-
-#[test]
-fn test_add_small() {
-    assert_eq!(*Big::from_small(3).add_small(4), Big::from_small(7));
-    assert_eq!(*Big::from_small(3).add_small(0), Big::from_small(3));
-    assert_eq!(*Big::from_small(0).add_small(3), Big::from_small(3));
-    assert_eq!(*Big::from_small(7).add_small(250), Big::from_u64(257));
-    assert_eq!(*Big::from_u64(0x7fff).add_small(1), Big::from_u64(0x8000));
-    assert_eq!(*Big::from_u64(0x2ffe).add_small(0x35), Big::from_u64(0x3033));
-    assert_eq!(*Big::from_small(0xdc).add_small(0x89), Big::from_u64(0x165));
-}
-
-#[test]
-#[should_panic]
-fn test_add_small_overflow() {
-    Big::from_u64(0xffffff).add_small(1);
-}
-
-#[test]
-fn test_sub() {
-    assert_eq!(*Big::from_small(7).sub(&Big::from_small(4)), Big::from_small(3));
-    assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x789)), Big::from_u64(0xfedc));
-    assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0xfedc)), Big::from_u64(0x789));
-    assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x10664)), Big::from_small(1));
-    assert_eq!(*Big::from_u64(0x10665).sub(&Big::from_u64(0x10665)), Big::from_small(0));
-}
-
-#[test]
-#[should_panic]
-fn test_sub_underflow_1() {
-    Big::from_u64(0x10665).sub(&Big::from_u64(0x10666));
-}
-
-#[test]
-#[should_panic]
-fn test_sub_underflow_2() {
-    Big::from_small(0).sub(&Big::from_u64(0x123456));
-}
-
-#[test]
-fn test_mul_small() {
-    assert_eq!(*Big::from_small(7).mul_small(5), Big::from_small(35));
-    assert_eq!(*Big::from_small(0xff).mul_small(0xff), Big::from_u64(0xfe01));
-    assert_eq!(*Big::from_u64(0xffffff/13).mul_small(13), Big::from_u64(0xffffff));
-}
-
-#[test]
-#[should_panic]
-fn test_mul_small_overflow() {
-    Big::from_u64(0x800000).mul_small(2);
-}
-
-#[test]
-fn test_mul_pow2() {
-    assert_eq!(*Big::from_small(0x7).mul_pow2(4), Big::from_small(0x70));
-    assert_eq!(*Big::from_small(0xff).mul_pow2(1), Big::from_u64(0x1fe));
-    assert_eq!(*Big::from_small(0xff).mul_pow2(12), Big::from_u64(0xff000));
-    assert_eq!(*Big::from_small(0x1).mul_pow2(23), Big::from_u64(0x800000));
-    assert_eq!(*Big::from_u64(0x123).mul_pow2(0), Big::from_u64(0x123));
-    assert_eq!(*Big::from_u64(0x123).mul_pow2(7), Big::from_u64(0x9180));
-    assert_eq!(*Big::from_u64(0x123).mul_pow2(15), Big::from_u64(0x918000));
-    assert_eq!(*Big::from_small(0).mul_pow2(23), Big::from_small(0));
-}
-
-#[test]
-#[should_panic]
-fn test_mul_pow2_overflow_1() {
-    Big::from_u64(0x1).mul_pow2(24);
-}
-
-#[test]
-#[should_panic]
-fn test_mul_pow2_overflow_2() {
-    Big::from_u64(0x123).mul_pow2(16);
-}
-
-#[test]
-fn test_mul_pow5() {
-    assert_eq!(*Big::from_small(42).mul_pow5(0), Big::from_small(42));
-    assert_eq!(*Big::from_small(1).mul_pow5(2), Big::from_small(25));
-    assert_eq!(*Big::from_small(1).mul_pow5(4), Big::from_u64(25 * 25));
-    assert_eq!(*Big::from_small(4).mul_pow5(3), Big::from_u64(500));
-    assert_eq!(*Big::from_small(140).mul_pow5(2), Big::from_u64(25 * 140));
-    assert_eq!(*Big::from_small(25).mul_pow5(1), Big::from_small(125));
-    assert_eq!(*Big::from_small(125).mul_pow5(7), Big::from_u64(9765625));
-    assert_eq!(*Big::from_small(0).mul_pow5(127), Big::from_small(0));
-}
-
-#[test]
-#[should_panic]
-fn test_mul_pow5_overflow_1() {
-    Big::from_small(1).mul_pow5(12);
-}
-
-#[test]
-#[should_panic]
-fn test_mul_pow5_overflow_2() {
-    Big::from_small(230).mul_pow5(8);
-}
-
-#[test]
-fn test_mul_digits() {
-    assert_eq!(*Big::from_small(3).mul_digits(&[5]), Big::from_small(15));
-    assert_eq!(*Big::from_small(0xff).mul_digits(&[0xff]), Big::from_u64(0xfe01));
-    assert_eq!(*Big::from_u64(0x123).mul_digits(&[0x56, 0x4]), Big::from_u64(0x4edc2));
-    assert_eq!(*Big::from_u64(0x12345).mul_digits(&[0x67]), Big::from_u64(0x7530c3));
-    assert_eq!(*Big::from_small(0x12).mul_digits(&[0x67, 0x45, 0x3]), Big::from_u64(0x3ae13e));
-    assert_eq!(*Big::from_u64(0xffffff/13).mul_digits(&[13]), Big::from_u64(0xffffff));
-    assert_eq!(*Big::from_small(13).mul_digits(&[0x3b, 0xb1, 0x13]), Big::from_u64(0xffffff));
-}
-
-#[test]
-#[should_panic]
-fn test_mul_digits_overflow_1() {
-    Big::from_u64(0x800000).mul_digits(&[2]);
-}
-
-#[test]
-#[should_panic]
-fn test_mul_digits_overflow_2() {
-    Big::from_u64(0x1000).mul_digits(&[0, 0x10]);
-}
-
-#[test]
-fn test_div_rem_small() {
-    let as_val = |(q, r): (&mut Big, u8)| (q.clone(), r);
-    assert_eq!(as_val(Big::from_small(0xff).div_rem_small(15)), (Big::from_small(17), 0));
-    assert_eq!(as_val(Big::from_small(0xff).div_rem_small(16)), (Big::from_small(15), 15));
-    assert_eq!(as_val(Big::from_small(3).div_rem_small(40)), (Big::from_small(0), 3));
-    assert_eq!(as_val(Big::from_u64(0xffffff).div_rem_small(123)),
-               (Big::from_u64(0xffffff / 123), (0xffffffu64 % 123) as u8));
-    assert_eq!(as_val(Big::from_u64(0x10000).div_rem_small(123)),
-               (Big::from_u64(0x10000 / 123), (0x10000u64 % 123) as u8));
-}
-
-#[test]
-fn test_div_rem() {
-    fn div_rem(n: u64, d: u64) -> (Big, Big) {
-        let mut q = Big::from_small(42);
-        let mut r = Big::from_small(42);
-        Big::from_u64(n).div_rem(&Big::from_u64(d), &mut q, &mut r);
-        (q, r)
-    }
-    assert_eq!(div_rem(1, 1), (Big::from_small(1), Big::from_small(0)));
-    assert_eq!(div_rem(4, 3), (Big::from_small(1), Big::from_small(1)));
-    assert_eq!(div_rem(1, 7), (Big::from_small(0), Big::from_small(1)));
-    assert_eq!(div_rem(45, 9), (Big::from_small(5), Big::from_small(0)));
-    assert_eq!(div_rem(103, 9), (Big::from_small(11), Big::from_small(4)));
-    assert_eq!(div_rem(123456, 77), (Big::from_u64(1603), Big::from_small(25)));
-    assert_eq!(div_rem(0xffff, 1), (Big::from_u64(0xffff), Big::from_small(0)));
-    assert_eq!(div_rem(0xeeee, 0xffff), (Big::from_small(0), Big::from_u64(0xeeee)));
-    assert_eq!(div_rem(2_000_000, 2), (Big::from_u64(1_000_000), Big::from_u64(0)));
-}
-
-#[test]
-fn test_is_zero() {
-    assert!(Big::from_small(0).is_zero());
-    assert!(!Big::from_small(3).is_zero());
-    assert!(!Big::from_u64(0x123).is_zero());
-    assert!(!Big::from_u64(0xffffff).sub(&Big::from_u64(0xfffffe)).is_zero());
-    assert!(Big::from_u64(0xffffff).sub(&Big::from_u64(0xffffff)).is_zero());
-}
-
-#[test]
-fn test_get_bit() {
-    let x = Big::from_small(0b1101);
-    assert_eq!(x.get_bit(0), 1);
-    assert_eq!(x.get_bit(1), 0);
-    assert_eq!(x.get_bit(2), 1);
-    assert_eq!(x.get_bit(3), 1);
-    let y = Big::from_u64(1 << 15);
-    assert_eq!(y.get_bit(14), 0);
-    assert_eq!(y.get_bit(15), 1);
-    assert_eq!(y.get_bit(16), 0);
-}
-
-#[test]
-#[should_panic]
-fn test_get_bit_out_of_range() {
-    Big::from_small(42).get_bit(24);
-}
-
-#[test]
-fn test_bit_length() {
-    assert_eq!(Big::from_small(0).bit_length(), 0);
-    assert_eq!(Big::from_small(1).bit_length(), 1);
-    assert_eq!(Big::from_small(5).bit_length(), 3);
-    assert_eq!(Big::from_small(0x18).bit_length(), 5);
-    assert_eq!(Big::from_u64(0x4073).bit_length(), 15);
-    assert_eq!(Big::from_u64(0xffffff).bit_length(), 24);
-}
-
-#[test]
-fn test_ord() {
-    assert!(Big::from_u64(0) < Big::from_u64(0xffffff));
-    assert!(Big::from_u64(0x102) < Big::from_u64(0x201));
-}
-
-#[test]
-fn test_fmt() {
-    assert_eq!(format!("{:?}", Big::from_u64(0)), "0x0");
-    assert_eq!(format!("{:?}", Big::from_u64(0x1)), "0x1");
-    assert_eq!(format!("{:?}", Big::from_u64(0x12)), "0x12");
-    assert_eq!(format!("{:?}", Big::from_u64(0x123)), "0x1_23");
-    assert_eq!(format!("{:?}", Big::from_u64(0x1234)), "0x12_34");
-    assert_eq!(format!("{:?}", Big::from_u64(0x12345)), "0x1_23_45");
-    assert_eq!(format!("{:?}", Big::from_u64(0x123456)), "0x12_34_56");
-}
-
index 8ae33a4420207038d5af70ba8818e56903d4f7f3..309bf6d8192188870433f8296f5646cb98dc9da9 100644 (file)
@@ -23,7 +23,6 @@ use core::num::flt2dec::{to_shortest_str, to_shortest_exp_str,
 pub use test::Bencher;
 
 mod estimator;
-mod bignum;
 mod strategy {
     mod dragon;
     mod grisu;
index f3ddc370d1e1403062f37d45116e9608172df216..79dcca7671a2d0215340f2185cc7338c41a62f60 100644 (file)
@@ -12,7 +12,7 @@ use std::prelude::v1::*;
 use std::{i16, f64};
 use super::super::*;
 use core::num::flt2dec::*;
-use core::num::flt2dec::bignum::Big32x40 as Big;
+use core::num::bignum::Big32x40 as Big;
 use core::num::flt2dec::strategy::dragon::*;
 
 #[test]
index 9f9d2a4ca1659b14d26930c0234ba577656b8285..5e2ec66bababebb362cce97e36ff38adcbbf730f 100644 (file)
@@ -31,6 +31,7 @@ mod u64;
 
 mod flt2dec;
 mod dec2flt;
+mod bignum;
 
 /// Helper function for testing numeric operations
 pub fn test_num<T>(ten: T, two: T) where
@@ -117,15 +118,63 @@ mod tests {
         assert_eq!("-9223372036854775809".parse::<i64>().ok(), None);
     }
 
+    #[test]
+    fn test_leading_plus() {
+        assert_eq!("+127".parse::<u8>().ok(), Some(127u8));
+        assert_eq!("+9223372036854775807".parse::<i64>().ok(), Some(9223372036854775807i64));
+    }
+
     #[test]
     fn test_invalid() {
         assert_eq!("--129".parse::<i8>().ok(), None);
+        assert_eq!("++129".parse::<i8>().ok(), None);
         assert_eq!("Съешь".parse::<u8>().ok(), None);
     }
 
     #[test]
     fn test_empty() {
         assert_eq!("-".parse::<i8>().ok(), None);
+        assert_eq!("+".parse::<i8>().ok(), None);
         assert_eq!("".parse::<u8>().ok(), None);
     }
+
+    macro_rules! test_impl_from {
+        ($fn_name: ident, $Small: ty, $Large: ty) => {
+            #[test]
+            fn $fn_name() {
+                let small_max = <$Small>::max_value();
+                let small_min = <$Small>::min_value();
+                let large_max: $Large = small_max.into();
+                let large_min: $Large = small_min.into();
+                assert_eq!(large_max as $Small, small_max);
+                assert_eq!(large_min as $Small, small_min);
+            }
+        }
+    }
+
+    // Unsigned -> Unsigned
+    test_impl_from! { test_u8u16, u8, u16 }
+    test_impl_from! { test_u8u32, u8, u32 }
+    test_impl_from! { test_u8u64, u8, u64 }
+    test_impl_from! { test_u8usize, u8, usize }
+    test_impl_from! { test_u16u32, u16, u32 }
+    test_impl_from! { test_u16u64, u16, u64 }
+    test_impl_from! { test_u32u64, u32, u64 }
+
+    // Signed -> Signed
+    test_impl_from! { test_i8i16, i8, i16 }
+    test_impl_from! { test_i8i32, i8, i32 }
+    test_impl_from! { test_i8i64, i8, i64 }
+    test_impl_from! { test_i8isize, i8, isize }
+    test_impl_from! { test_i16i32, i16, i32 }
+    test_impl_from! { test_i16i64, i16, i64 }
+    test_impl_from! { test_i32i64, i32, i64 }
+
+    // Unsigned -> Signed
+    test_impl_from! { test_u8i16, u8, i16 }
+    test_impl_from! { test_u8i32, u8, i32 }
+    test_impl_from! { test_u8i64, u8, i64 }
+    test_impl_from! { test_u16i32, u16, i32 }
+    test_impl_from! { test_u16i64, u16, i64 }
+    test_impl_from! { test_u32i64, u32, i64 }
 }
index d85f653937c8056e55b645e0449af68d5308e3dc..521dddae78ff964dceeeb41524e865d784426b30 100644 (file)
@@ -30,7 +30,9 @@
 #![feature(unique)]
 #![cfg_attr(test, feature(rustc_private, rand, vec_push_all))]
 
-#[cfg(test)] #[macro_use] extern crate log;
+#[cfg(test)]
+#[macro_use]
+extern crate log;
 
 extern crate libc;
 
@@ -47,9 +49,7 @@ pub struct Error {
 
 impl Error {
     fn new() -> Error {
-        Error {
-            _unused: (),
-        }
+        Error { _unused: () }
     }
 }
 
@@ -73,7 +73,9 @@ impl Deref for Bytes {
 
 impl Drop for Bytes {
     fn drop(&mut self) {
-        unsafe { libc::free(*self.ptr as *mut _); }
+        unsafe {
+            libc::free(*self.ptr as *mut _);
+        }
     }
 }
 
@@ -123,7 +125,7 @@ pub fn deflate_bytes_zlib(bytes: &[u8]) -> Bytes {
     deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER)
 }
 
-fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Result<Bytes,Error> {
+fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Result<Bytes, Error> {
     unsafe {
         let mut outsz: size_t = 0;
         let res = tinfl_decompress_mem_to_heap(bytes.as_ptr() as *const _,
@@ -142,12 +144,12 @@ fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Result<Bytes,Error> {
 }
 
 /// Decompress a buffer, without parsing any sort of header on the input.
-pub fn inflate_bytes(bytes: &[u8]) -> Result<Bytes,Error> {
+pub fn inflate_bytes(bytes: &[u8]) -> Result<Bytes, Error> {
     inflate_bytes_internal(bytes, 0)
 }
 
 /// Decompress a buffer that starts with a zlib header.
-pub fn inflate_bytes_zlib(bytes: &[u8]) -> Result<Bytes,Error> {
+pub fn inflate_bytes_zlib(bytes: &[u8]) -> Result<Bytes, Error> {
     inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER)
 }
 
@@ -176,7 +178,8 @@ mod tests {
             let cmp = deflate_bytes(&input);
             let out = inflate_bytes(&cmp).unwrap();
             debug!("{} bytes deflated to {} ({:.1}% size)",
-                   input.len(), cmp.len(),
+                   input.len(),
+                   cmp.len(),
                    100.0 * ((cmp.len() as f64) / (input.len() as f64)));
             assert_eq!(&*input, &*out);
         }
index 9c02ccb08acd84764f56d94a307842916b80e1e2..ed767ab1e5cf97e3116deb0d01ad71b37cc04682 100644 (file)
@@ -75,7 +75,7 @@ pub struct FormatSpec<'a> {
     /// The descriptor string representing the name of the format desired for
     /// this argument, this can be empty or any number of characters, although
     /// it is required to be one word.
-    pub ty: &'a str
+    pub ty: &'a str,
 }
 
 /// Enum describing where an argument for a format can be located.
@@ -135,7 +135,7 @@ pub enum Count<'a> {
 }
 
 /// The parser structure for interpreting the input format string. This is
-/// modelled as an iterator over `Piece` structures to form a stream of tokens
+/// modeled as an iterator over `Piece` structures to form a stream of tokens
 /// being output.
 ///
 /// This is a recursive-descent parser for the sake of simplicity, and if
@@ -202,7 +202,12 @@ impl<'a> Parser<'a> {
     /// returned, otherwise the character is consumed and true is returned.
     fn consume(&mut self, c: char) -> bool {
         if let Some(&(_, maybe)) = self.cur.peek() {
-            if c == maybe { self.cur.next(); true } else { false }
+            if c == maybe {
+                self.cur.next();
+                true
+            } else {
+                false
+            }
         } else {
             false
         }
@@ -227,7 +232,11 @@ impl<'a> Parser<'a> {
     /// character
     fn ws(&mut self) {
         while let Some(&(_, c)) = self.cur.peek() {
-            if c.is_whitespace() { self.cur.next(); } else { break }
+            if c.is_whitespace() {
+                self.cur.next();
+            } else {
+                break
+            }
         }
     }
 
@@ -237,8 +246,12 @@ impl<'a> Parser<'a> {
         // we may not consume the character, peek the iterator
         while let Some(&(pos, c)) = self.cur.peek() {
             match c {
-                '{' | '}' => { return &self.input[start..pos]; }
-                _ => { self.cur.next(); }
+                '{' | '}' => {
+                    return &self.input[start..pos];
+                }
+                _ => {
+                    self.cur.next();
+                }
             }
         }
         &self.input[start..self.input.len()]
@@ -263,7 +276,7 @@ impl<'a> Parser<'a> {
                 Some(&(_, c)) if c.is_alphabetic() => {
                     ArgumentNamed(self.word())
                 }
-                _ => ArgumentNext
+                _ => ArgumentNext,
             }
         }
     }
@@ -279,7 +292,9 @@ impl<'a> Parser<'a> {
             width: CountImplied,
             ty: &self.input[..0],
         };
-        if !self.consume(':') { return spec }
+        if !self.consume(':') {
+            return spec
+        }
 
         // fill character
         if let Some(&(_, c)) = self.cur.peek() {
@@ -347,7 +362,11 @@ impl<'a> Parser<'a> {
     /// width.
     fn count(&mut self) -> Count<'a> {
         if let Some(i) = self.integer() {
-            if self.consume('$') { CountIsParam(i) } else { CountIs(i) }
+            if self.consume('$') {
+                CountIsParam(i)
+            } else {
+                CountIs(i)
+            }
         } else {
             let tmp = self.cur.clone();
             let word = self.word();
@@ -370,8 +389,13 @@ impl<'a> Parser<'a> {
     /// characters.
     fn word(&mut self) -> &'a str {
         let start = match self.cur.peek() {
-            Some(&(pos, c)) if c.is_xid_start() => { self.cur.next(); pos }
-            _ => { return &self.input[..0]; }
+            Some(&(pos, c)) if c.is_xid_start() => {
+                self.cur.next();
+                pos
+            }
+            _ => {
+                return &self.input[..0];
+            }
         };
         while let Some(&(pos, c)) = self.cur.peek() {
             if c.is_xid_continue() {
@@ -397,7 +421,11 @@ impl<'a> Parser<'a> {
                 break
             }
         }
-        if found { Some(cur) } else { None }
+        if found {
+            Some(cur)
+        } else {
+            None
+        }
     }
 }
 
@@ -437,178 +465,210 @@ mod tests {
         same("\\}}", &[String("\\"), String("}")]);
     }
 
-    #[test] fn invalid01() { musterr("{") }
-    #[test] fn invalid02() { musterr("}") }
-    #[test] fn invalid04() { musterr("{3a}") }
-    #[test] fn invalid05() { musterr("{:|}") }
-    #[test] fn invalid06() { musterr("{:>>>}") }
+    #[test]
+    fn invalid01() {
+        musterr("{")
+    }
+    #[test]
+    fn invalid02() {
+        musterr("}")
+    }
+    #[test]
+    fn invalid04() {
+        musterr("{3a}")
+    }
+    #[test]
+    fn invalid05() {
+        musterr("{:|}")
+    }
+    #[test]
+    fn invalid06() {
+        musterr("{:>>>}")
+    }
 
     #[test]
     fn format_nothing() {
-        same("{}", &[NextArgument(Argument {
-            position: ArgumentNext,
-            format: fmtdflt(),
-        })]);
+        same("{}",
+             &[NextArgument(Argument {
+                   position: ArgumentNext,
+                   format: fmtdflt(),
+               })]);
     }
     #[test]
     fn format_position() {
-        same("{3}", &[NextArgument(Argument {
-            position: ArgumentIs(3),
-            format: fmtdflt(),
-        })]);
+        same("{3}",
+             &[NextArgument(Argument {
+                   position: ArgumentIs(3),
+                   format: fmtdflt(),
+               })]);
     }
     #[test]
     fn format_position_nothing_else() {
-        same("{3:}", &[NextArgument(Argument {
-            position: ArgumentIs(3),
-            format: fmtdflt(),
-        })]);
+        same("{3:}",
+             &[NextArgument(Argument {
+                   position: ArgumentIs(3),
+                   format: fmtdflt(),
+               })]);
     }
     #[test]
     fn format_type() {
-        same("{3:a}", &[NextArgument(Argument {
-            position: ArgumentIs(3),
-            format: FormatSpec {
-                fill: None,
-                align: AlignUnknown,
-                flags: 0,
-                precision: CountImplied,
-                width: CountImplied,
-                ty: "a",
-            },
-        })]);
+        same("{3:a}",
+             &[NextArgument(Argument {
+                   position: ArgumentIs(3),
+                   format: FormatSpec {
+                       fill: None,
+                       align: AlignUnknown,
+                       flags: 0,
+                       precision: CountImplied,
+                       width: CountImplied,
+                       ty: "a",
+                   },
+               })]);
     }
     #[test]
     fn format_align_fill() {
-        same("{3:>}", &[NextArgument(Argument {
-            position: ArgumentIs(3),
-            format: FormatSpec {
-                fill: None,
-                align: AlignRight,
-                flags: 0,
-                precision: CountImplied,
-                width: CountImplied,
-                ty: "",
-            },
-        })]);
-        same("{3:0<}", &[NextArgument(Argument {
-            position: ArgumentIs(3),
-            format: FormatSpec {
-                fill: Some('0'),
-                align: AlignLeft,
-                flags: 0,
-                precision: CountImplied,
-                width: CountImplied,
-                ty: "",
-            },
-        })]);
-        same("{3:*<abcd}", &[NextArgument(Argument {
-            position: ArgumentIs(3),
-            format: FormatSpec {
-                fill: Some('*'),
-                align: AlignLeft,
-                flags: 0,
-                precision: CountImplied,
-                width: CountImplied,
-                ty: "abcd",
-            },
-        })]);
+        same("{3:>}",
+             &[NextArgument(Argument {
+                   position: ArgumentIs(3),
+                   format: FormatSpec {
+                       fill: None,
+                       align: AlignRight,
+                       flags: 0,
+                       precision: CountImplied,
+                       width: CountImplied,
+                       ty: "",
+                   },
+               })]);
+        same("{3:0<}",
+             &[NextArgument(Argument {
+                   position: ArgumentIs(3),
+                   format: FormatSpec {
+                       fill: Some('0'),
+                       align: AlignLeft,
+                       flags: 0,
+                       precision: CountImplied,
+                       width: CountImplied,
+                       ty: "",
+                   },
+               })]);
+        same("{3:*<abcd}",
+             &[NextArgument(Argument {
+                   position: ArgumentIs(3),
+                   format: FormatSpec {
+                       fill: Some('*'),
+                       align: AlignLeft,
+                       flags: 0,
+                       precision: CountImplied,
+                       width: CountImplied,
+                       ty: "abcd",
+                   },
+               })]);
     }
     #[test]
     fn format_counts() {
-        same("{:10s}", &[NextArgument(Argument {
-            position: ArgumentNext,
-            format: FormatSpec {
-                fill: None,
-                align: AlignUnknown,
-                flags: 0,
-                precision: CountImplied,
-                width: CountIs(10),
-                ty: "s",
-            },
-        })]);
-        same("{:10$.10s}", &[NextArgument(Argument {
-            position: ArgumentNext,
-            format: FormatSpec {
-                fill: None,
-                align: AlignUnknown,
-                flags: 0,
-                precision: CountIs(10),
-                width: CountIsParam(10),
-                ty: "s",
-            },
-        })]);
-        same("{:.*s}", &[NextArgument(Argument {
-            position: ArgumentNext,
-            format: FormatSpec {
-                fill: None,
-                align: AlignUnknown,
-                flags: 0,
-                precision: CountIsNextParam,
-                width: CountImplied,
-                ty: "s",
-            },
-        })]);
-        same("{:.10$s}", &[NextArgument(Argument {
-            position: ArgumentNext,
-            format: FormatSpec {
-                fill: None,
-                align: AlignUnknown,
-                flags: 0,
-                precision: CountIsParam(10),
-                width: CountImplied,
-                ty: "s",
-            },
-        })]);
-        same("{:a$.b$s}", &[NextArgument(Argument {
-            position: ArgumentNext,
-            format: FormatSpec {
-                fill: None,
-                align: AlignUnknown,
-                flags: 0,
-                precision: CountIsName("b"),
-                width: CountIsName("a"),
-                ty: "s",
-            },
-        })]);
+        same("{:10s}",
+             &[NextArgument(Argument {
+                   position: ArgumentNext,
+                   format: FormatSpec {
+                       fill: None,
+                       align: AlignUnknown,
+                       flags: 0,
+                       precision: CountImplied,
+                       width: CountIs(10),
+                       ty: "s",
+                   },
+               })]);
+        same("{:10$.10s}",
+             &[NextArgument(Argument {
+                   position: ArgumentNext,
+                   format: FormatSpec {
+                       fill: None,
+                       align: AlignUnknown,
+                       flags: 0,
+                       precision: CountIs(10),
+                       width: CountIsParam(10),
+                       ty: "s",
+                   },
+               })]);
+        same("{:.*s}",
+             &[NextArgument(Argument {
+                   position: ArgumentNext,
+                   format: FormatSpec {
+                       fill: None,
+                       align: AlignUnknown,
+                       flags: 0,
+                       precision: CountIsNextParam,
+                       width: CountImplied,
+                       ty: "s",
+                   },
+               })]);
+        same("{:.10$s}",
+             &[NextArgument(Argument {
+                   position: ArgumentNext,
+                   format: FormatSpec {
+                       fill: None,
+                       align: AlignUnknown,
+                       flags: 0,
+                       precision: CountIsParam(10),
+                       width: CountImplied,
+                       ty: "s",
+                   },
+               })]);
+        same("{:a$.b$s}",
+             &[NextArgument(Argument {
+                   position: ArgumentNext,
+                   format: FormatSpec {
+                       fill: None,
+                       align: AlignUnknown,
+                       flags: 0,
+                       precision: CountIsName("b"),
+                       width: CountIsName("a"),
+                       ty: "s",
+                   },
+               })]);
     }
     #[test]
     fn format_flags() {
-        same("{:-}", &[NextArgument(Argument {
-            position: ArgumentNext,
-            format: FormatSpec {
-                fill: None,
-                align: AlignUnknown,
-                flags: (1 << FlagSignMinus as u32),
-                precision: CountImplied,
-                width: CountImplied,
-                ty: "",
-            },
-        })]);
-        same("{:+#}", &[NextArgument(Argument {
-            position: ArgumentNext,
-            format: FormatSpec {
-                fill: None,
-                align: AlignUnknown,
-                flags: (1 << FlagSignPlus as u32) | (1 << FlagAlternate as u32),
-                precision: CountImplied,
-                width: CountImplied,
-                ty: "",
-            },
-        })]);
+        same("{:-}",
+             &[NextArgument(Argument {
+                   position: ArgumentNext,
+                   format: FormatSpec {
+                       fill: None,
+                       align: AlignUnknown,
+                       flags: (1 << FlagSignMinus as u32),
+                       precision: CountImplied,
+                       width: CountImplied,
+                       ty: "",
+                   },
+               })]);
+        same("{:+#}",
+             &[NextArgument(Argument {
+                   position: ArgumentNext,
+                   format: FormatSpec {
+                       fill: None,
+                       align: AlignUnknown,
+                       flags: (1 << FlagSignPlus as u32) | (1 << FlagAlternate as u32),
+                       precision: CountImplied,
+                       width: CountImplied,
+                       ty: "",
+                   },
+               })]);
     }
     #[test]
     fn format_mixture() {
-        same("abcd {3:a} efg", &[String("abcd "), NextArgument(Argument {
-            position: ArgumentIs(3),
-            format: FormatSpec {
-                fill: None,
-                align: AlignUnknown,
-                flags: 0,
-                precision: CountImplied,
-                width: CountImplied,
-                ty: "a",
-            },
-        }), String(" efg")]);
+        same("abcd {3:a} efg",
+             &[String("abcd "),
+               NextArgument(Argument {
+                   position: ArgumentIs(3),
+                   format: FormatSpec {
+                       fill: None,
+                       align: AlignUnknown,
+                       flags: 0,
+                       precision: CountImplied,
+                       width: CountImplied,
+                       ty: "a",
+                   },
+               }),
+               String(" efg")]);
     }
 }
index 7fafe97efc9ee34c156c108607d8fd28fff5dfa3..b82b7d122b3ce8205c760602202243faed391eeb 100644 (file)
@@ -456,7 +456,7 @@ pub trait Labeller<'a,N,E> {
     fn graph_id(&'a self) -> Id<'a>;
 
     /// Maps `n` to a unique identifier with respect to `self`. The
-    /// implementer is responsible for ensuring that the returned name
+    /// implementor is responsible for ensuring that the returned name
     /// is a valid DOT identifier.
     fn node_id(&'a self, n: &N) -> Id<'a>;
 
@@ -594,7 +594,7 @@ pub type Edges<'a,E> = Cow<'a,[E]>;
 /// that is bound by the self lifetime `'a`.
 ///
 /// The `nodes` and `edges` method each return instantiations of
-/// `Cow<[T]>` to leave implementers the freedom to create
+/// `Cow<[T]>` to leave implementors the freedom to create
 /// entirely new vectors or to pass back slices into internally owned
 /// vectors.
 pub trait GraphWalk<'a, N: Clone, E: Clone> {
index 95b5ccca75397bb7514c72a40836cc060ef4df2b..13902d674379eb6a13a4781d5e7867dfa3de4b08 100644 (file)
@@ -24,6 +24,7 @@
        html_playground_url = "https://play.rust-lang.org/",
        issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
 #![cfg_attr(test, feature(test))]
+#![cfg_attr(not(feature = "cargo-build"), feature(cfg_target_vendor))]
 
 //! Bindings for the C standard library and other platform libraries
 //!
 
 #![allow(bad_style, raw_pointer_derive)]
 #![cfg_attr(target_os = "nacl", allow(unused_imports))]
-#[cfg(feature = "cargo-build")] extern crate std as core;
+#[cfg(feature = "cargo-build")]
+extern crate std as core;
 
-#[cfg(test)] extern crate std;
-#[cfg(test)] extern crate test;
+#[cfg(test)]
+extern crate std;
+#[cfg(test)]
+extern crate test;
 
 // Explicit export lists for the intersection (provided here) mean that
 // you can write more-platform-agnostic code if you stick to just these
@@ -127,46 +131,63 @@ pub use funcs::bsd43::*;
 //
 // So the following exports don't follow any particular plan.
 
-#[cfg(unix)] pub use consts::os::sysconf::*;
-
-#[cfg(unix)] pub use funcs::posix88::mman::*;
-#[cfg(unix)] pub use funcs::posix88::dirent::*;
-#[cfg(unix)] pub use funcs::posix88::net::*;
-#[cfg(unix)] pub use funcs::posix01::stat_::*;
-#[cfg(unix)] pub use funcs::posix01::unistd::*;
-#[cfg(unix)] pub use funcs::posix01::resource::*;
-
-
-#[cfg(windows)] pub use funcs::extra::kernel32::*;
-#[cfg(windows)] pub use funcs::extra::winsock::*;
-#[cfg(windows)] pub use funcs::extra::msvcrt::*;
+#[cfg(unix)]
+pub use consts::os::sysconf::*;
+
+#[cfg(unix)]
+pub use funcs::posix88::mman::*;
+#[cfg(unix)]
+pub use funcs::posix88::dirent::*;
+#[cfg(unix)]
+pub use funcs::posix88::net::*;
+#[cfg(unix)]
+pub use funcs::posix01::stat_::*;
+#[cfg(unix)]
+pub use funcs::posix01::unistd::*;
+#[cfg(unix)]
+pub use funcs::posix01::resource::*;
+
+
+#[cfg(windows)]
+pub use funcs::extra::kernel32::*;
+#[cfg(windows)]
+pub use funcs::extra::winsock::*;
+#[cfg(windows)]
+pub use funcs::extra::msvcrt::*;
 
 // On NaCl, these libraries are static. Thus it would be a Bad Idea to link them
 // in when creating a test crate.
-#[cfg(not(any(windows, target_env = "musl", all(target_os = "nacl", test))))]
+#[cfg(not(any(windows,
+              target_env = "musl",
+              all(target_os = "nacl", test),
+              all(target_os = "netbsd", target_vendor = "rumprun"))))]
 #[link(name = "c")]
 #[link(name = "m")]
-extern {}
+extern {
+}
 
 // When compiling rust with musl, statically include libc.a in liblibc.rlib.
 // A cargo build of the libc crate will therefore automatically pick up the
 // libc.a symbols because liblibc is transitively linked to by the stdlib.
 #[cfg(all(target_env = "musl", not(feature = "cargo-build"), not(test)))]
 #[link(name = "c", kind = "static")]
-extern {}
+extern {
+}
 
 #[cfg(all(windows, target_env = "msvc"))]
 #[link(name = "kernel32")]
 #[link(name = "shell32")]
 #[link(name = "msvcrt")]
-extern {}
+extern {
+}
 
 // libnacl provides functions that require a trip through the IRT to work.
 // ie: _exit, mmap, nanosleep, etc. Anything that would otherwise require a trip
 // to the kernel.
 #[cfg(all(target_os = "nacl", not(feature = "cargo-build"), not(test)))]
 #[link(name = "nacl", kind = "static")]
-extern {}
+extern {
+}
 
 // pnaclmm provides a number of functions that the toolchain's Clang emits calls
 // to when codegening atomic ops. All the functions within wrap various atomic
@@ -176,7 +197,8 @@ extern {}
 // optimizations on the whole pnaclmm foreach binary built).
 #[cfg(all(target_os = "nacl", not(feature = "cargo-build"), not(test)))]
 #[link(name = "pnaclmm", kind = "static")]
-extern {}
+extern {
+}
 
 pub mod types {
 
@@ -222,9 +244,12 @@ pub mod types {
             pub enum DIR {}
             pub enum dirent_t {}
         }
-        pub mod posix01 {}
-        pub mod posix08 {}
-        pub mod bsd44 {}
+        pub mod posix01 {
+        }
+        pub mod posix08 {
+        }
+        pub mod bsd44 {
+        }
     }
 
     // Standard types that are scalar but vary by OS and arch.
@@ -233,9 +258,8 @@ pub mod types {
     pub mod os {
         pub mod common {
             pub mod posix01 {
-                use types::common::c95::{c_void};
-                use types::os::arch::c95::{c_char, c_ulong, size_t,
-                                                 time_t, suseconds_t, c_long};
+                use types::common::c95::c_void;
+                use types::os::arch::c95::{c_char, c_ulong, size_t, time_t, suseconds_t, c_long};
 
                 #[cfg(not(target_os = "nacl"))]
                 pub type pthread_t = c_ulong;
@@ -244,10 +268,11 @@ pub mod types {
                 pub type rlim_t = u64;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct glob_t {
+                #[derive(Copy, Clone)]
+                pub struct glob_t {
                     pub gl_pathc: size_t,
                     pub gl_pathv: *mut *mut c_char,
-                    pub gl_offs:  size_t,
+                    pub gl_offs: size_t,
 
                     pub __unused1: *mut c_void,
                     pub __unused2: *mut c_void,
@@ -257,13 +282,15 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct timeval {
+                #[derive(Copy, Clone)]
+                pub struct timeval {
                     pub tv_sec: time_t,
                     pub tv_usec: suseconds_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct timespec {
+                #[derive(Copy, Clone)]
+                pub struct timespec {
                     pub tv_sec: time_t,
                     pub tv_nsec: c_long,
                 }
@@ -303,12 +330,12 @@ pub mod types {
                     pub ru_msgrcv: c_long,
                     pub ru_nsignals: c_long,
                     pub ru_nvcsw: c_long,
-                    pub ru_nivcsw: c_long
+                    pub ru_nivcsw: c_long,
                 }
             }
 
             pub mod bsd44 {
-                use types::common::c95::{c_void};
+                use types::common::c95::c_void;
                 use types::os::arch::c95::{c_char, c_int, c_uint};
 
                 pub type socklen_t = u32;
@@ -316,12 +343,14 @@ pub mod types {
                 pub type in_port_t = u16;
                 pub type in_addr_t = u32;
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr {
                     pub sa_family: sa_family_t,
                     pub sa_data: [u8; 14],
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_storage {
+                #[derive(Copy)]
+                pub struct sockaddr_storage {
                     pub ss_family: sa_family_t,
                     pub __ss_align: isize,
                     #[cfg(target_pointer_width = "32")]
@@ -330,21 +359,26 @@ pub mod types {
                     pub __ss_pad2: [u8; 128 - 2 * 8],
                 }
                 impl ::core::clone::Clone for sockaddr_storage {
-                    fn clone(&self) -> sockaddr_storage { *self }
+                    fn clone(&self) -> sockaddr_storage {
+                        *self
+                    }
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr_in {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr_in {
                     pub sin_family: sa_family_t,
                     pub sin_port: in_port_t,
                     pub sin_addr: in_addr,
                     pub sin_zero: [u8; 8],
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct in_addr {
+                #[derive(Copy, Clone)]
+                pub struct in_addr {
                     pub s_addr: in_addr_t,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr_in6 {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr_in6 {
                     pub sin6_family: sa_family_t,
                     pub sin6_port: in_port_t,
                     pub sin6_flowinfo: u32,
@@ -352,21 +386,25 @@ pub mod types {
                     pub sin6_scope_id: u32,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct in6_addr {
-                    pub s6_addr: [u16; 8]
+                #[derive(Copy, Clone)]
+                pub struct in6_addr {
+                    pub s6_addr: [u16; 8],
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct ip_mreq {
+                #[derive(Copy, Clone)]
+                pub struct ip_mreq {
                     pub imr_multiaddr: in_addr,
                     pub imr_interface: in_addr,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct ip6_mreq {
+                #[derive(Copy, Clone)]
+                pub struct ip6_mreq {
                     pub ipv6mr_multiaddr: in6_addr,
                     pub ipv6mr_interface: c_uint,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct addrinfo {
+                #[derive(Copy, Clone)]
+                pub struct addrinfo {
                     pub ai_flags: c_int,
                     pub ai_family: c_int,
                     pub ai_socktype: c_int,
@@ -388,23 +426,27 @@ pub mod types {
                     pub ai_next: *mut addrinfo,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_un {
+                #[derive(Copy)]
+                pub struct sockaddr_un {
                     pub sun_family: sa_family_t,
-                    pub sun_path: [c_char; 108]
+                    pub sun_path: [c_char; 108],
                 }
                 impl ::core::clone::Clone for sockaddr_un {
-                    fn clone(&self) -> sockaddr_un { *self }
+                    fn clone(&self) -> sockaddr_un {
+                        *self
+                    }
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct ifaddrs {
+                #[derive(Copy, Clone)]
+                pub struct ifaddrs {
                     pub ifa_next: *mut ifaddrs,
                     pub ifa_name: *mut c_char,
                     pub ifa_flags: c_uint,
                     pub ifa_addr: *mut sockaddr,
                     pub ifa_netmask: *mut sockaddr,
                     pub ifa_ifu: *mut sockaddr, // FIXME This should be a union
-                    pub ifa_data: *mut c_void
+                    pub ifa_data: *mut c_void,
                 }
 
             }
@@ -484,14 +526,15 @@ pub mod types {
                 use types::os::arch::c95::{c_short, c_long, time_t};
                 use types::os::arch::posix88::{dev_t, gid_t, ino_t};
                 use types::os::arch::posix88::{mode_t, off_t};
-                use types::os::arch::posix88::{uid_t};
+                use types::os::arch::posix88::uid_t;
 
                 pub type nlink_t = u32;
                 pub type blksize_t = i32;
                 pub type blkcnt_t = i32;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct stat {
+                #[derive(Copy, Clone)]
+                pub struct stat {
                     pub st_dev: dev_t,
                     pub __pad1: c_short,
                     pub st_ino: ino_t,
@@ -515,14 +558,16 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct utimbuf {
+                #[derive(Copy, Clone)]
+                pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct pthread_attr_t {
-                    pub __size: [u32; 9]
+                #[derive(Copy, Clone)]
+                pub struct pthread_attr_t {
+                    pub __size: [u32; 9],
                 }
             }
 
@@ -538,7 +583,8 @@ pub mod types {
                 pub type blkcnt_t = u32;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct stat {
+                #[derive(Copy, Clone)]
+                pub struct stat {
                     pub st_dev: c_ulonglong,
                     pub __pad0: [c_uchar; 4],
                     pub __st_ino: c_long,
@@ -561,14 +607,16 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct utimbuf {
+                #[derive(Copy, Clone)]
+                pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct pthread_attr_t {
-                    pub __size: [u32; 9]
+                #[derive(Copy, Clone)]
+                pub struct pthread_attr_t {
+                    pub __size: [u32; 9],
                 }
             }
 
@@ -578,14 +626,15 @@ pub mod types {
                 use types::os::arch::c95::{c_long, c_ulong, time_t};
                 use types::os::arch::posix88::{gid_t, ino_t};
                 use types::os::arch::posix88::{mode_t, off_t};
-                use types::os::arch::posix88::{uid_t};
+                use types::os::arch::posix88::uid_t;
 
                 pub type nlink_t = u32;
                 pub type blksize_t = i32;
                 pub type blkcnt_t = i32;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct stat {
+                #[derive(Copy, Clone)]
+                pub struct stat {
                     pub st_dev: c_ulong,
                     pub st_pad1: [c_long; 3],
                     pub st_ino: ino_t,
@@ -609,29 +658,34 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct utimbuf {
+                #[derive(Copy, Clone)]
+                pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct pthread_attr_t {
-                    pub __size: [u32; 9]
+                #[derive(Copy, Clone)]
+                pub struct pthread_attr_t {
+                    pub __size: [u32; 9],
                 }
             }
-            pub mod posix08 {}
-            pub mod bsd44 {}
+            pub mod posix08 {
+            }
+            pub mod bsd44 {
+            }
             pub mod extra {
                 use types::os::arch::c95::{c_ushort, c_int, c_uchar};
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr_ll {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr_ll {
                     pub sll_family: c_ushort,
                     pub sll_protocol: c_ushort,
                     pub sll_ifindex: c_int,
                     pub sll_hatype: c_ushort,
                     pub sll_pkttype: c_uchar,
                     pub sll_halen: c_uchar,
-                    pub sll_addr: [c_uchar; 8]
+                    pub sll_addr: [c_uchar; 8],
                 }
             }
 
@@ -689,14 +743,15 @@ pub mod types {
                 use types::os::arch::c95::{c_int, c_long, time_t};
                 use types::os::arch::posix88::{dev_t, gid_t, ino_t};
                 use types::os::arch::posix88::{mode_t, off_t};
-                use types::os::arch::posix88::{uid_t};
+                use types::os::arch::posix88::uid_t;
 
                 pub type nlink_t = u64;
                 pub type blksize_t = i64;
                 pub type blkcnt_t = i64;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct stat {
+                #[derive(Copy, Clone)]
+                pub struct stat {
                     pub st_dev: dev_t,
                     pub st_ino: ino_t,
                     pub st_nlink: nlink_t,
@@ -718,14 +773,16 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct utimbuf {
+                #[derive(Copy, Clone)]
+                pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct pthread_attr_t {
-                    pub __size: [u64; 7]
+                #[derive(Copy, Clone)]
+                pub struct pthread_attr_t {
+                    pub __size: [u64; 7],
                 }
             }
             #[cfg(target_arch = "aarch64")]
@@ -733,14 +790,15 @@ pub mod types {
                 use types::os::arch::c95::{c_int, c_long, time_t};
                 use types::os::arch::posix88::{dev_t, gid_t, ino_t};
                 use types::os::arch::posix88::{mode_t, off_t};
-                use types::os::arch::posix88::{uid_t};
+                use types::os::arch::posix88::uid_t;
 
                 pub type nlink_t = u32;
                 pub type blksize_t = i32;
                 pub type blkcnt_t = i64;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct stat {
+                #[derive(Copy, Clone)]
+                pub struct stat {
                     pub st_dev: dev_t,
                     pub st_ino: ino_t,
                     pub st_mode: mode_t,
@@ -763,14 +821,16 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct utimbuf {
+                #[derive(Copy, Clone)]
+                pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct pthread_attr_t {
-                    pub __size: [u64; 8]
+                #[derive(Copy, Clone)]
+                pub struct pthread_attr_t {
+                    pub __size: [u64; 8],
                 }
             }
             pub mod posix08 {
@@ -779,14 +839,15 @@ pub mod types {
             }
             pub mod extra {
                 use types::os::arch::c95::{c_ushort, c_int, c_uchar};
-                #[derive(Copy, Clone)] pub struct sockaddr_ll {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr_ll {
                     pub sll_family: c_ushort,
                     pub sll_protocol: c_ushort,
                     pub sll_ifindex: c_int,
                     pub sll_hatype: c_ushort,
                     pub sll_pkttype: c_uchar,
                     pub sll_halen: c_uchar,
-                    pub sll_addr: [c_uchar; 8]
+                    pub sll_addr: [c_uchar; 8],
                 }
 
             }
@@ -797,21 +858,21 @@ pub mod types {
     pub mod os {
         pub mod common {
             pub mod posix01 {
-                use types::common::c95::{c_void};
-                use types::os::arch::c95::{c_char, c_int, size_t,
-                                                 time_t, suseconds_t, c_long};
-                use types::os::arch::c99::{uintptr_t};
+                use types::common::c95::c_void;
+                use types::os::arch::c95::{c_char, c_int, size_t, time_t, suseconds_t, c_long};
+                use types::os::arch::c99::uintptr_t;
 
                 pub type pthread_t = uintptr_t;
                 pub type rlim_t = i64;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct glob_t {
-                    pub gl_pathc:  size_t,
+                #[derive(Copy, Clone)]
+                pub struct glob_t {
+                    pub gl_pathc: size_t,
                     pub __unused1: size_t,
-                    pub gl_offs:   size_t,
+                    pub gl_offs: size_t,
                     pub __unused2: c_int,
-                    pub gl_pathv:  *mut *mut c_char,
+                    pub gl_pathv: *mut *mut c_char,
 
                     pub __unused3: *mut c_void,
 
@@ -823,13 +884,15 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct timeval {
+                #[derive(Copy, Clone)]
+                pub struct timeval {
                     pub tv_sec: time_t,
                     pub tv_usec: suseconds_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct timespec {
+                #[derive(Copy, Clone)]
+                pub struct timespec {
                     pub tv_sec: time_t,
                     pub tv_nsec: c_long,
                 }
@@ -867,12 +930,12 @@ pub mod types {
                     pub ru_msgrcv: c_long,
                     pub ru_nsignals: c_long,
                     pub ru_nvcsw: c_long,
-                    pub ru_nivcsw: c_long
+                    pub ru_nivcsw: c_long,
                 }
             }
 
             pub mod bsd44 {
-                use types::common::c95::{c_void};
+                use types::common::c95::c_void;
                 use types::os::arch::c95::{c_char, c_int, c_uint};
 
                 pub type socklen_t = u32;
@@ -880,13 +943,15 @@ pub mod types {
                 pub type in_port_t = u16;
                 pub type in_addr_t = u32;
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr {
                     pub sa_len: u8,
                     pub sa_family: sa_family_t,
                     pub sa_data: [u8; 14],
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_storage {
+                #[derive(Copy)]
+                pub struct sockaddr_storage {
                     pub ss_len: u8,
                     pub ss_family: sa_family_t,
                     pub __ss_pad1: [u8; 6],
@@ -894,10 +959,13 @@ pub mod types {
                     pub __ss_pad2: [u8; 112],
                 }
                 impl ::core::clone::Clone for sockaddr_storage {
-                    fn clone(&self) -> sockaddr_storage { *self }
+                    fn clone(&self) -> sockaddr_storage {
+                        *self
+                    }
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr_in {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr_in {
                     pub sin_len: u8,
                     pub sin_family: sa_family_t,
                     pub sin_port: in_port_t,
@@ -905,11 +973,13 @@ pub mod types {
                     pub sin_zero: [u8; 8],
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct in_addr {
+                #[derive(Copy, Clone)]
+                pub struct in_addr {
                     pub s_addr: in_addr_t,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr_in6 {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr_in6 {
                     pub sin6_len: u8,
                     pub sin6_family: sa_family_t,
                     pub sin6_port: in_port_t,
@@ -918,21 +988,25 @@ pub mod types {
                     pub sin6_scope_id: u32,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct in6_addr {
-                    pub s6_addr: [u16; 8]
+                #[derive(Copy, Clone)]
+                pub struct in6_addr {
+                    pub s6_addr: [u16; 8],
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct ip_mreq {
+                #[derive(Copy, Clone)]
+                pub struct ip_mreq {
                     pub imr_multiaddr: in_addr,
                     pub imr_interface: in_addr,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct ip6_mreq {
+                #[derive(Copy, Clone)]
+                pub struct ip6_mreq {
                     pub ipv6mr_multiaddr: in6_addr,
                     pub ipv6mr_interface: c_uint,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct addrinfo {
+                #[derive(Copy, Clone)]
+                pub struct addrinfo {
                     pub ai_flags: c_int,
                     pub ai_family: c_int,
                     pub ai_socktype: c_int,
@@ -943,23 +1017,27 @@ pub mod types {
                     pub ai_next: *mut addrinfo,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_un {
+                #[derive(Copy)]
+                pub struct sockaddr_un {
                     pub sun_len: u8,
                     pub sun_family: sa_family_t,
-                    pub sun_path: [c_char; 104]
+                    pub sun_path: [c_char; 104],
                 }
                 impl ::core::clone::Clone for sockaddr_un {
-                    fn clone(&self) -> sockaddr_un { *self }
+                    fn clone(&self) -> sockaddr_un {
+                        *self
+                    }
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct ifaddrs {
+                #[derive(Copy, Clone)]
+                pub struct ifaddrs {
                     pub ifa_next: *mut ifaddrs,
                     pub ifa_name: *mut c_char,
                     pub ifa_flags: c_uint,
                     pub ifa_addr: *mut sockaddr,
                     pub ifa_netmask: *mut sockaddr,
                     pub ifa_dstaddr: *mut sockaddr,
-                    pub ifa_data: *mut c_void
+                    pub ifa_data: *mut c_void,
                 }
 
 
@@ -1007,19 +1085,20 @@ pub mod types {
                 pub type ssize_t = i32;
             }
             pub mod posix01 {
-                use types::common::c95::{c_void};
+                use types::common::c95::c_void;
                 use types::common::c99::{uint32_t, int32_t};
                 use types::os::arch::c95::{c_long, time_t};
                 use types::os::arch::posix88::{dev_t, gid_t, ino_t};
                 use types::os::arch::posix88::{mode_t, off_t};
-                use types::os::arch::posix88::{uid_t};
+                use types::os::arch::posix88::uid_t;
 
                 pub type nlink_t = u16;
                 pub type blksize_t = u32;
                 pub type blkcnt_t = i64;
                 pub type fflags_t = u32;
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct stat {
+                #[derive(Copy, Clone)]
+                pub struct stat {
                     pub st_dev: dev_t,
                     pub st_ino: ino_t,
                     pub st_mode: mode_t,
@@ -1045,7 +1124,8 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct utimbuf {
+                #[derive(Copy, Clone)]
+                pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
@@ -1101,19 +1181,20 @@ pub mod types {
                 pub type ssize_t = i64;
             }
             pub mod posix01 {
-                use types::common::c95::{c_void};
+                use types::common::c95::c_void;
                 use types::common::c99::{uint32_t, int32_t};
                 use types::os::arch::c95::{c_long, time_t};
                 use types::os::arch::posix88::{dev_t, gid_t, ino_t};
                 use types::os::arch::posix88::{mode_t, off_t};
-                use types::os::arch::posix88::{uid_t};
+                use types::os::arch::posix88::uid_t;
 
                 pub type nlink_t = u16;
                 pub type blksize_t = u32;
                 pub type blkcnt_t = i64;
                 pub type fflags_t = u32;
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct stat {
+                #[derive(Copy, Clone)]
+                pub struct stat {
                     pub st_dev: dev_t,
                     pub st_ino: ino_t,
                     pub st_mode: mode_t,
@@ -1138,7 +1219,8 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct utimbuf {
+                #[derive(Copy, Clone)]
+                pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
@@ -1158,21 +1240,21 @@ pub mod types {
     pub mod os {
         pub mod common {
             pub mod posix01 {
-                use types::common::c95::{c_void};
-                use types::os::arch::c95::{c_char, c_int, size_t,
-                                                 time_t, suseconds_t, c_long};
-                use types::os::arch::c99::{uintptr_t};
+                use types::common::c95::c_void;
+                use types::os::arch::c95::{c_char, c_int, size_t, time_t, suseconds_t, c_long};
+                use types::os::arch::c99::uintptr_t;
 
                 pub type pthread_t = uintptr_t;
                 pub type rlim_t = i64;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct glob_t {
-                    pub gl_pathc:  size_t,
+                #[derive(Copy, Clone)]
+                pub struct glob_t {
+                    pub gl_pathc: size_t,
                     pub __unused1: size_t,
-                    pub gl_offs:   size_t,
+                    pub gl_offs: size_t,
                     pub __unused2: c_int,
-                    pub gl_pathv:  *mut *mut c_char,
+                    pub gl_pathv: *mut *mut c_char,
 
                     pub __unused3: *mut c_void,
 
@@ -1184,13 +1266,15 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct timeval {
+                #[derive(Copy, Clone)]
+                pub struct timeval {
                     pub tv_sec: time_t,
                     pub tv_usec: suseconds_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct timespec {
+                #[derive(Copy, Clone)]
+                pub struct timespec {
                     pub tv_sec: time_t,
                     pub tv_nsec: c_long,
                 }
@@ -1228,12 +1312,12 @@ pub mod types {
                     pub ru_msgrcv: c_long,
                     pub ru_nsignals: c_long,
                     pub ru_nvcsw: c_long,
-                    pub ru_nivcsw: c_long
+                    pub ru_nivcsw: c_long,
                 }
             }
 
             pub mod bsd44 {
-                use types::common::c95::{c_void};
+                use types::common::c95::c_void;
                 use types::os::arch::c95::{c_char, c_int, c_uint};
 
                 pub type socklen_t = u32;
@@ -1241,13 +1325,15 @@ pub mod types {
                 pub type in_port_t = u16;
                 pub type in_addr_t = u32;
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr {
                     pub sa_len: u8,
                     pub sa_family: sa_family_t,
                     pub sa_data: [u8; 14],
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_storage {
+                #[derive(Copy)]
+                pub struct sockaddr_storage {
                     pub ss_len: u8,
                     pub ss_family: sa_family_t,
                     pub __ss_pad1: [u8; 6],
@@ -1255,10 +1341,13 @@ pub mod types {
                     pub __ss_pad2: [u8; 112],
                 }
                 impl ::core::clone::Clone for sockaddr_storage {
-                    fn clone(&self) -> sockaddr_storage { *self }
+                    fn clone(&self) -> sockaddr_storage {
+                        *self
+                    }
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr_in {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr_in {
                     pub sin_len: u8,
                     pub sin_family: sa_family_t,
                     pub sin_port: in_port_t,
@@ -1266,11 +1355,13 @@ pub mod types {
                     pub sin_zero: [u8; 8],
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct in_addr {
+                #[derive(Copy, Clone)]
+                pub struct in_addr {
                     pub s_addr: in_addr_t,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr_in6 {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr_in6 {
                     pub sin6_len: u8,
                     pub sin6_family: sa_family_t,
                     pub sin6_port: in_port_t,
@@ -1279,21 +1370,25 @@ pub mod types {
                     pub sin6_scope_id: u32,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct in6_addr {
-                    pub s6_addr: [u16; 8]
+                #[derive(Copy, Clone)]
+                pub struct in6_addr {
+                    pub s6_addr: [u16; 8],
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct ip_mreq {
+                #[derive(Copy, Clone)]
+                pub struct ip_mreq {
                     pub imr_multiaddr: in_addr,
                     pub imr_interface: in_addr,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct ip6_mreq {
+                #[derive(Copy, Clone)]
+                pub struct ip6_mreq {
                     pub ipv6mr_multiaddr: in6_addr,
                     pub ipv6mr_interface: c_uint,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct addrinfo {
+                #[derive(Copy, Clone)]
+                pub struct addrinfo {
                     pub ai_flags: c_int,
                     pub ai_family: c_int,
                     pub ai_socktype: c_int,
@@ -1304,23 +1399,27 @@ pub mod types {
                     pub ai_next: *mut addrinfo,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_un {
+                #[derive(Copy)]
+                pub struct sockaddr_un {
                     pub sun_len: u8,
                     pub sun_family: sa_family_t,
-                    pub sun_path: [c_char; 104]
+                    pub sun_path: [c_char; 104],
                 }
                 impl ::core::clone::Clone for sockaddr_un {
-                    fn clone(&self) -> sockaddr_un { *self }
+                    fn clone(&self) -> sockaddr_un {
+                        *self
+                    }
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct ifaddrs {
+                #[derive(Copy, Clone)]
+                pub struct ifaddrs {
                     pub ifa_next: *mut ifaddrs,
                     pub ifa_name: *mut c_char,
                     pub ifa_flags: c_uint,
                     pub ifa_addr: *mut sockaddr,
                     pub ifa_netmask: *mut sockaddr,
                     pub ifa_dstaddr: *mut sockaddr,
-                    pub ifa_data: *mut c_void
+                    pub ifa_data: *mut c_void,
                 }
 
             }
@@ -1366,12 +1465,12 @@ pub mod types {
                 pub type ssize_t = i64;
             }
             pub mod posix01 {
-                use types::common::c95::{c_void};
+                use types::common::c95::c_void;
                 use types::common::c99::{uint16_t, uint32_t, int32_t, uint64_t, int64_t};
                 use types::os::arch::c95::{c_long, time_t};
                 use types::os::arch::posix88::{dev_t, gid_t};
                 use types::os::arch::posix88::{mode_t, off_t};
-                use types::os::arch::posix88::{uid_t};
+                use types::os::arch::posix88::uid_t;
 
                 pub type nlink_t = u16;
                 pub type blksize_t = uint32_t;
@@ -1380,7 +1479,8 @@ pub mod types {
                 pub type fflags_t = u32;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct stat {
+                #[derive(Copy, Clone)]
+                pub struct stat {
                     pub st_ino: ino_t,
                     pub st_nlink: nlink_t,
                     pub st_dev: dev_t,
@@ -1405,7 +1505,8 @@ pub mod types {
                     pub st_qspare2: int64_t,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct utimbuf {
+                #[derive(Copy, Clone)]
+                pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
@@ -1425,22 +1526,22 @@ pub mod types {
     pub mod os {
         pub mod common {
             pub mod posix01 {
-                use types::common::c95::{c_void};
-                use types::os::arch::c95::{c_char, c_int, size_t,
-                                                 time_t, suseconds_t, c_long};
-                use types::os::arch::c99::{uintptr_t};
+                use types::common::c95::c_void;
+                use types::os::arch::c95::{c_char, c_int, size_t, time_t, suseconds_t, c_long};
+                use types::os::arch::c99::uintptr_t;
 
                 pub type pthread_t = uintptr_t;
                 pub type rlim_t = u64;
 
                 #[cfg(target_os = "bitrig")]
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct glob_t {
-                    pub gl_pathc:  c_int,
+                #[derive(Copy, Clone)]
+                pub struct glob_t {
+                    pub gl_pathc: c_int,
                     pub gl_matchc: c_int,
-                    pub gl_offs:   c_int,
-                    pub gl_flags:  c_int,
-                    pub gl_pathv:  *mut *mut c_char,
+                    pub gl_offs: c_int,
+                    pub gl_flags: c_int,
+                    pub gl_pathv: *mut *mut c_char,
                     pub __unused1: *mut c_void,
                     pub __unused2: *mut c_void,
                     pub __unused3: *mut c_void,
@@ -1450,14 +1551,32 @@ pub mod types {
                     pub __unused7: *mut c_void,
                 }
 
-                #[cfg(any(target_os = "netbsd", target_os="openbsd"))]
+                #[cfg(target_os = "netbsd")]
+                #[repr(C)]
+                #[derive(Copy, Clone)]
+                pub struct glob_t {
+                    pub gl_pathc: size_t,
+                    pub gl_matchc: size_t,
+                    pub gl_offs: size_t,
+                    pub gl_flags: c_int,
+                    pub gl_pathv: *mut *mut c_char,
+                    pub __unused1: *mut c_void,
+                    pub __unused2: *mut c_void,
+                    pub __unused3: *mut c_void,
+                    pub __unused4: *mut c_void,
+                    pub __unused5: *mut c_void,
+                    pub __unused6: *mut c_void,
+                }
+
+                #[cfg(target_os = "openbsd")]
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct glob_t {
-                    pub gl_pathc:  c_int,
+                #[derive(Copy, Clone)]
+                pub struct glob_t {
+                    pub gl_pathc: c_int,
                     pub __unused1: c_int,
-                    pub gl_offs:   c_int,
+                    pub gl_offs: c_int,
                     pub __unused2: c_int,
-                    pub gl_pathv:  *mut *mut c_char,
+                    pub gl_pathv: *mut *mut c_char,
 
                     pub __unused3: *mut c_void,
 
@@ -1470,13 +1589,15 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct timeval {
+                #[derive(Copy, Clone)]
+                pub struct timeval {
                     pub tv_sec: time_t,
                     pub tv_usec: suseconds_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct timespec {
+                #[derive(Copy, Clone)]
+                pub struct timespec {
                     pub tv_sec: time_t,
                     pub tv_nsec: c_long,
                 }
@@ -1514,12 +1635,12 @@ pub mod types {
                     pub ru_msgrcv: c_long,
                     pub ru_nsignals: c_long,
                     pub ru_nvcsw: c_long,
-                    pub ru_nivcsw: c_long
+                    pub ru_nivcsw: c_long,
                 }
             }
 
             pub mod bsd44 {
-                use types::common::c95::{c_void};
+                use types::common::c95::c_void;
                 use types::os::arch::c95::{c_char, c_int, c_uint};
 
                 pub type socklen_t = u32;
@@ -1527,13 +1648,15 @@ pub mod types {
                 pub type in_port_t = u16;
                 pub type in_addr_t = u32;
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr {
                     pub sa_len: u8,
                     pub sa_family: sa_family_t,
                     pub sa_data: [u8; 14],
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_storage {
+                #[derive(Copy)]
+                pub struct sockaddr_storage {
                     pub ss_len: u8,
                     pub ss_family: sa_family_t,
                     pub __ss_pad1: [u8; 6],
@@ -1541,10 +1664,13 @@ pub mod types {
                     pub __ss_pad3: [u8; 240],
                 }
                 impl ::core::clone::Clone for sockaddr_storage {
-                    fn clone(&self) -> sockaddr_storage { *self }
+                    fn clone(&self) -> sockaddr_storage {
+                        *self
+                    }
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr_in {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr_in {
                     pub sin_len: u8,
                     pub sin_family: sa_family_t,
                     pub sin_port: in_port_t,
@@ -1552,11 +1678,13 @@ pub mod types {
                     pub sin_zero: [u8; 8],
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct in_addr {
+                #[derive(Copy, Clone)]
+                pub struct in_addr {
                     pub s_addr: in_addr_t,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr_in6 {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr_in6 {
                     pub sin6_len: u8,
                     pub sin6_family: sa_family_t,
                     pub sin6_port: in_port_t,
@@ -1565,21 +1693,26 @@ pub mod types {
                     pub sin6_scope_id: u32,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct in6_addr {
-                    pub s6_addr: [u16; 8]
+                #[derive(Copy, Clone)]
+                pub struct in6_addr {
+                    pub s6_addr: [u16; 8],
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct ip_mreq {
+                #[derive(Copy, Clone)]
+                pub struct ip_mreq {
                     pub imr_multiaddr: in_addr,
                     pub imr_interface: in_addr,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct ip6_mreq {
+                #[derive(Copy, Clone)]
+                pub struct ip6_mreq {
                     pub ipv6mr_multiaddr: in6_addr,
                     pub ipv6mr_interface: c_uint,
                 }
+                #[cfg(not(target_os = "netbsd"))]
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct addrinfo {
+                #[derive(Copy, Clone)]
+                pub struct addrinfo {
                     pub ai_flags: c_int,
                     pub ai_family: c_int,
                     pub ai_socktype: c_int,
@@ -1589,24 +1722,41 @@ pub mod types {
                     pub ai_canonname: *mut c_char,
                     pub ai_next: *mut addrinfo,
                 }
+                #[cfg(target_os = "netbsd")]
+                #[repr(C)]
+                #[derive(Copy, Clone)]
+                pub struct addrinfo {
+                    pub ai_flags: c_int,
+                    pub ai_family: c_int,
+                    pub ai_socktype: c_int,
+                    pub ai_protocol: c_int,
+                    pub ai_addrlen: socklen_t,
+                    pub ai_canonname: *mut c_char,
+                    pub ai_addr: *mut sockaddr,
+                    pub ai_next: *mut addrinfo,
+                }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_un {
+                #[derive(Copy)]
+                pub struct sockaddr_un {
                     pub sun_len: u8,
                     pub sun_family: sa_family_t,
-                    pub sun_path: [c_char; 104]
+                    pub sun_path: [c_char; 104],
                 }
                 impl ::core::clone::Clone for sockaddr_un {
-                    fn clone(&self) -> sockaddr_un { *self }
+                    fn clone(&self) -> sockaddr_un {
+                        *self
+                    }
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct ifaddrs {
+                #[derive(Copy, Clone)]
+                pub struct ifaddrs {
                     pub ifa_next: *mut ifaddrs,
                     pub ifa_name: *mut c_char,
                     pub ifa_flags: c_uint,
                     pub ifa_addr: *mut sockaddr,
                     pub ifa_netmask: *mut sockaddr,
                     pub ifa_dstaddr: *mut sockaddr,
-                    pub ifa_data: *mut c_void
+                    pub ifa_data: *mut c_void,
                 }
             }
         }
@@ -1641,7 +1791,7 @@ pub mod types {
                 pub type uintmax_t = u64;
             }
             pub mod posix88 {
-                use types::os::arch::c95::{c_long};
+                use types::os::arch::c95::c_long;
                 pub type off_t = i64;
                 pub type dev_t = i32;
                 pub type pid_t = i32;
@@ -1652,12 +1802,14 @@ pub mod types {
                 pub type ssize_t = c_long;
             }
             pub mod posix01 {
-                use types::common::c95::{c_void};
+                use types::common::c95::c_void;
                 use types::common::c99::{uint32_t, uint64_t};
                 use types::os::arch::c95::{c_long, time_t};
                 use types::os::arch::posix88::{dev_t, gid_t};
                 use types::os::arch::posix88::{mode_t, off_t};
-                use types::os::arch::posix88::{uid_t};
+                use types::os::arch::posix88::uid_t;
+                #[cfg(target_os = "netbsd")]
+                use types::os::arch::c95::{c_int, c_uint};
 
                 pub type nlink_t = uint32_t;
                 pub type blksize_t = uint32_t;
@@ -1665,8 +1817,10 @@ pub mod types {
                 pub type blkcnt_t = i64;
                 pub type fflags_t = u32; // type not declared, but struct stat have u_int32_t
 
+                #[cfg(not(target_os = "netbsd"))]
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct stat {
+                #[derive(Copy, Clone)]
+                pub struct stat {
                     pub st_mode: mode_t,
                     pub st_dev: dev_t,
                     pub st_ino: ino_t,
@@ -1688,13 +1842,50 @@ pub mod types {
                     pub st_birthtime: time_t,
                     pub st_birthtime_nsec: c_long,
                 }
+                #[cfg(target_os = "netbsd")]
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct utimbuf {
+                #[derive(Copy, Clone)]
+                pub struct stat {
+                    pub st_mode: mode_t,
+                    pub st_dev: dev_t,
+                    pub st_ino: ino_t,
+                    pub st_nlink: nlink_t,
+                    pub st_uid: uid_t,
+                    pub st_gid: gid_t,
+                    pub st_rdev: dev_t,
+                    pub st_atime: time_t,
+                    pub st_atime_nsec: c_long,
+                    pub st_mtime: time_t,
+                    pub st_mtime_nsec: c_long,
+                    pub st_ctime: time_t,
+                    pub st_ctime_nsec: c_long,
+                    pub st_birthtime: time_t,
+                    pub st_birthtime_nsec: c_long,
+                    pub st_size: off_t,
+                    pub st_blocks: blkcnt_t,
+                    pub st_blksize: blksize_t,
+                    pub st_flags: fflags_t,
+                    pub st_gen: uint32_t,
+                    st_spare: [uint32_t; 2],
+                }
+
+                #[repr(C)]
+                #[derive(Copy, Clone)]
+                pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
 
+                #[cfg(not(target_os = "netbsd"))]
                 pub type pthread_attr_t = *mut c_void;
+                #[cfg(target_os = "netbsd")]
+                #[repr(C)]
+                #[derive(Copy, Clone)]
+                pub struct pthread_attr_t {
+                    pta_magic: c_uint,
+                    pta_flags: c_int,
+                    pta_private: *mut c_void,
+                }
             }
             pub mod posix08 {
             }
@@ -1716,7 +1907,8 @@ pub mod types {
                 // pub Note: this is the struct called stat64 in Windows. Not stat,
                 // nor stati64.
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct stat {
+                #[derive(Copy, Clone)]
+                pub struct stat {
                     pub st_dev: dev_t,
                     pub st_ino: ino_t,
                     pub st_mode: u16,
@@ -1732,19 +1924,22 @@ pub mod types {
 
                 // note that this is called utimbuf64 in Windows
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct utimbuf {
+                #[derive(Copy, Clone)]
+                pub struct utimbuf {
                     pub actime: time64_t,
                     pub modtime: time64_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct timeval {
+                #[derive(Copy, Clone)]
+                pub struct timeval {
                     pub tv_sec: c_long,
                     pub tv_usec: c_long,
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct timespec {
+                #[derive(Copy, Clone)]
+                pub struct timespec {
                     pub tv_sec: time_t,
                     pub tv_nsec: c_long,
                 }
@@ -1762,33 +1957,40 @@ pub mod types {
                 pub type in_port_t = u16;
                 pub type in_addr_t = u32;
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr {
                     pub sa_family: sa_family_t,
                     pub sa_data: [u8; 14],
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_storage {
+                #[derive(Copy)]
+                pub struct sockaddr_storage {
                     pub ss_family: sa_family_t,
                     pub __ss_pad1: [u8; 6],
                     pub __ss_align: i64,
                     pub __ss_pad2: [u8; 112],
                 }
                 impl ::core::clone::Clone for sockaddr_storage {
-                    fn clone(&self) -> sockaddr_storage { *self }
+                    fn clone(&self) -> sockaddr_storage {
+                        *self
+                    }
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr_in {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr_in {
                     pub sin_family: sa_family_t,
                     pub sin_port: in_port_t,
                     pub sin_addr: in_addr,
                     pub sin_zero: [u8; 8],
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct in_addr {
+                #[derive(Copy, Clone)]
+                pub struct in_addr {
                     pub s_addr: in_addr_t,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr_in6 {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr_in6 {
                     pub sin6_family: sa_family_t,
                     pub sin6_port: in_port_t,
                     pub sin6_flowinfo: u32,
@@ -1796,21 +1998,25 @@ pub mod types {
                     pub sin6_scope_id: u32,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct in6_addr {
-                    pub s6_addr: [u16; 8]
+                #[derive(Copy, Clone)]
+                pub struct in6_addr {
+                    pub s6_addr: [u16; 8],
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct ip_mreq {
+                #[derive(Copy, Clone)]
+                pub struct ip_mreq {
                     pub imr_multiaddr: in_addr,
                     pub imr_interface: in_addr,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct ip6_mreq {
+                #[derive(Copy, Clone)]
+                pub struct ip6_mreq {
                     pub ipv6mr_multiaddr: in6_addr,
                     pub ipv6mr_interface: c_uint,
                 }
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct addrinfo {
+                #[derive(Copy, Clone)]
+                pub struct addrinfo {
                     pub ai_flags: c_int,
                     pub ai_family: c_int,
                     pub ai_socktype: c_int,
@@ -1821,12 +2027,15 @@ pub mod types {
                     pub ai_next: *mut addrinfo,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_un {
+                #[derive(Copy)]
+                pub struct sockaddr_un {
                     pub sun_family: sa_family_t,
-                    pub sun_path: [c_char; 108]
+                    pub sun_path: [c_char; 108],
                 }
                 impl ::core::clone::Clone for sockaddr_un {
-                    fn clone(&self) -> sockaddr_un { *self }
+                    fn clone(&self) -> sockaddr_un {
+                        *self
+                    }
                 }
             }
         }
@@ -1911,12 +2120,11 @@ pub mod types {
             pub mod bsd44 {
             }
             pub mod extra {
-                use consts::os::extra::{MAX_PROTOCOL_CHAIN,
-                                              WSAPROTOCOL_LEN};
+                use consts::os::extra::{MAX_PROTOCOL_CHAIN, WSAPROTOCOL_LEN};
                 use types::common::c95::c_void;
                 use types::os::arch::c95::{c_char, c_int, c_uint, size_t};
                 use types::os::arch::c95::{c_long, c_ulong};
-                use types::os::arch::c95::{wchar_t};
+                use types::os::arch::c95::wchar_t;
                 use types::os::arch::c99::{c_ulonglong, c_longlong, uintptr_t};
 
                 pub type BOOL = c_int;
@@ -1953,7 +2161,8 @@ pub mod types {
                 pub type LPCH = *mut CHAR;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct SECURITY_ATTRIBUTES {
+                #[derive(Copy, Clone)]
+                pub struct SECURITY_ATTRIBUTES {
                     pub nLength: DWORD,
                     pub lpSecurityDescriptor: LPVOID,
                     pub bInheritHandle: BOOL,
@@ -1977,7 +2186,8 @@ pub mod types {
                 pub type int64 = i64;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct STARTUPINFO {
+                #[derive(Copy, Clone)]
+                pub struct STARTUPINFO {
                     pub cb: DWORD,
                     pub lpReserved: LPWSTR,
                     pub lpDesktop: LPWSTR,
@@ -2000,7 +2210,8 @@ pub mod types {
                 pub type LPSTARTUPINFO = *mut STARTUPINFO;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct PROCESS_INFORMATION {
+                #[derive(Copy, Clone)]
+                pub struct PROCESS_INFORMATION {
                     pub hProcess: HANDLE,
                     pub hThread: HANDLE,
                     pub dwProcessId: DWORD,
@@ -2009,7 +2220,8 @@ pub mod types {
                 pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct SYSTEM_INFO {
+                #[derive(Copy, Clone)]
+                pub struct SYSTEM_INFO {
                     pub wProcessorArchitecture: WORD,
                     pub wReserved: WORD,
                     pub dwPageSize: DWORD,
@@ -2025,7 +2237,8 @@ pub mod types {
                 pub type LPSYSTEM_INFO = *mut SYSTEM_INFO;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct MEMORY_BASIC_INFORMATION {
+                #[derive(Copy, Clone)]
+                pub struct MEMORY_BASIC_INFORMATION {
                     pub BaseAddress: LPVOID,
                     pub AllocationBase: LPVOID,
                     pub AllocationProtect: DWORD,
@@ -2037,7 +2250,8 @@ pub mod types {
                 pub type LPMEMORY_BASIC_INFORMATION = *mut MEMORY_BASIC_INFORMATION;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct OVERLAPPED {
+                #[derive(Copy, Clone)]
+                pub struct OVERLAPPED {
                     pub Internal: *mut c_ulong,
                     pub InternalHigh: *mut c_ulong,
                     pub Offset: DWORD,
@@ -2048,7 +2262,8 @@ pub mod types {
                 pub type LPOVERLAPPED = *mut OVERLAPPED;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct FILETIME {
+                #[derive(Copy, Clone)]
+                pub struct FILETIME {
                     pub dwLowDateTime: DWORD,
                     pub dwHighDateTime: DWORD,
                 }
@@ -2056,7 +2271,8 @@ pub mod types {
                 pub type LPFILETIME = *mut FILETIME;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct GUID {
+                #[derive(Copy, Clone)]
+                pub struct GUID {
                     pub Data1: DWORD,
                     pub Data2: WORD,
                     pub Data3: WORD,
@@ -2064,7 +2280,8 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct WSAPROTOCOLCHAIN {
+                #[derive(Copy, Clone)]
+                pub struct WSAPROTOCOLCHAIN {
                     pub ChainLen: c_int,
                     pub ChainEntries: [DWORD; MAX_PROTOCOL_CHAIN as usize],
                 }
@@ -2072,7 +2289,8 @@ pub mod types {
                 pub type LPWSAPROTOCOLCHAIN = *mut WSAPROTOCOLCHAIN;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct WSAPROTOCOL_INFO {
+                #[derive(Copy)]
+                pub struct WSAPROTOCOL_INFO {
                     pub dwServiceFlags1: DWORD,
                     pub dwServiceFlags2: DWORD,
                     pub dwServiceFlags3: DWORD,
@@ -2092,10 +2310,12 @@ pub mod types {
                     pub iSecurityScheme: c_int,
                     pub dwMessageSize: DWORD,
                     pub dwProviderReserved: DWORD,
-                    pub szProtocol: [u8; WSAPROTOCOL_LEN as usize + 1],
+                    pub szProtocol: [u8; (WSAPROTOCOL_LEN as usize) + 1],
                 }
                 impl ::core::clone::Clone for WSAPROTOCOL_INFO {
-                    fn clone(&self) -> WSAPROTOCOL_INFO { *self }
+                    fn clone(&self) -> WSAPROTOCOL_INFO {
+                        *self
+                    }
                 }
 
                 pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;
@@ -2103,7 +2323,8 @@ pub mod types {
                 pub type GROUP = c_uint;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct WIN32_FIND_DATAW {
+                #[derive(Copy)]
+                pub struct WIN32_FIND_DATAW {
                     pub dwFileAttributes: DWORD,
                     pub ftCreationTime: FILETIME,
                     pub ftLastAccessTime: FILETIME,
@@ -2116,7 +2337,9 @@ pub mod types {
                     pub cAlternateFileName: [wchar_t; 14],
                 }
                 impl ::core::clone::Clone for WIN32_FIND_DATAW {
-                    fn clone(&self) -> WIN32_FIND_DATAW { *self }
+                    fn clone(&self) -> WIN32_FIND_DATAW {
+                        *self
+                    }
                 }
 
                 pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW;
@@ -2131,18 +2354,19 @@ pub mod types {
                 use types::common::c95::c_void;
                 use types::os::arch::c95::{c_char, c_int, size_t, time_t};
                 use types::os::arch::c95::{suseconds_t, c_long};
-                use types::os::arch::c99::{uintptr_t};
+                use types::os::arch::c99::uintptr_t;
 
                 pub type pthread_t = uintptr_t;
                 pub type rlim_t = u64;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct glob_t {
-                    pub gl_pathc:  size_t,
+                #[derive(Copy, Clone)]
+                pub struct glob_t {
+                    pub gl_pathc: size_t,
                     pub __unused1: c_int,
-                    pub gl_offs:   size_t,
+                    pub gl_offs: size_t,
                     pub __unused2: c_int,
-                    pub gl_pathv:  *mut *mut c_char,
+                    pub gl_pathv: *mut *mut c_char,
 
                     pub __unused3: *mut c_void,
 
@@ -2154,13 +2378,15 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct timeval {
+                #[derive(Copy, Clone)]
+                pub struct timeval {
                     pub tv_sec: time_t,
                     pub tv_usec: suseconds_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct timespec {
+                #[derive(Copy, Clone)]
+                pub struct timespec {
                     pub tv_sec: time_t,
                     pub tv_nsec: c_long,
                 }
@@ -2198,12 +2424,12 @@ pub mod types {
                     pub ru_msgrcv: c_long,
                     pub ru_nsignals: c_long,
                     pub ru_nvcsw: c_long,
-                    pub ru_nivcsw: c_long
+                    pub ru_nivcsw: c_long,
                 }
             }
 
             pub mod bsd44 {
-                use types::common::c95::{c_void};
+                use types::common::c95::c_void;
                 use types::os::arch::c95::{c_char, c_int, c_uint};
 
                 pub type socklen_t = u32;
@@ -2211,14 +2437,16 @@ pub mod types {
                 pub type in_port_t = u16;
                 pub type in_addr_t = u32;
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr {
                     pub sa_len: u8,
                     pub sa_family: sa_family_t,
                     pub sa_data: [u8; 14],
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_storage {
+                #[derive(Copy)]
+                pub struct sockaddr_storage {
                     pub ss_len: u8,
                     pub ss_family: sa_family_t,
                     pub __ss_pad1: [u8; 6],
@@ -2226,11 +2454,14 @@ pub mod types {
                     pub __ss_pad2: [u8; 112],
                 }
                 impl ::core::clone::Clone for sockaddr_storage {
-                    fn clone(&self) -> sockaddr_storage { *self }
+                    fn clone(&self) -> sockaddr_storage {
+                        *self
+                    }
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr_in {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr_in {
                     pub sin_len: u8,
                     pub sin_family: sa_family_t,
                     pub sin_port: in_port_t,
@@ -2239,12 +2470,14 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct in_addr {
+                #[derive(Copy, Clone)]
+                pub struct in_addr {
                     pub s_addr: in_addr_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct sockaddr_in6 {
+                #[derive(Copy, Clone)]
+                pub struct sockaddr_in6 {
                     pub sin6_len: u8,
                     pub sin6_family: sa_family_t,
                     pub sin6_port: in_port_t,
@@ -2254,24 +2487,28 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct in6_addr {
-                    pub s6_addr: [u16; 8]
+                #[derive(Copy, Clone)]
+                pub struct in6_addr {
+                    pub s6_addr: [u16; 8],
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct ip_mreq {
+                #[derive(Copy, Clone)]
+                pub struct ip_mreq {
                     pub imr_multiaddr: in_addr,
                     pub imr_interface: in_addr,
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct ip6_mreq {
+                #[derive(Copy, Clone)]
+                pub struct ip6_mreq {
                     pub ipv6mr_multiaddr: in6_addr,
                     pub ipv6mr_interface: c_uint,
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct addrinfo {
+                #[derive(Copy, Clone)]
+                pub struct addrinfo {
                     pub ai_flags: c_int,
                     pub ai_family: c_int,
                     pub ai_socktype: c_int,
@@ -2283,24 +2520,28 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_un {
+                #[derive(Copy)]
+                pub struct sockaddr_un {
                     pub sun_len: u8,
                     pub sun_family: sa_family_t,
-                    pub sun_path: [c_char; 104]
+                    pub sun_path: [c_char; 104],
                 }
                 impl ::core::clone::Clone for sockaddr_un {
-                    fn clone(&self) -> sockaddr_un { *self }
+                    fn clone(&self) -> sockaddr_un {
+                        *self
+                    }
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct ifaddrs {
+                #[derive(Copy, Clone)]
+                pub struct ifaddrs {
                     pub ifa_next: *mut ifaddrs,
                     pub ifa_name: *mut c_char,
                     pub ifa_flags: c_uint,
                     pub ifa_addr: *mut sockaddr,
                     pub ifa_netmask: *mut sockaddr,
                     pub ifa_dstaddr: *mut sockaddr,
-                    pub ifa_data: *mut c_void
+                    pub ifa_data: *mut c_void,
                 }
             }
         }
@@ -2350,15 +2591,15 @@ pub mod types {
             pub mod posix01 {
                 use types::common::c99::{int32_t, int64_t, uint32_t};
                 use types::os::arch::c95::{c_char, c_long, time_t};
-                use types::os::arch::posix88::{dev_t, gid_t, ino_t,
-                                                     mode_t, off_t, uid_t};
+                use types::os::arch::posix88::{dev_t, gid_t, ino_t, mode_t, off_t, uid_t};
 
                 pub type nlink_t = u16;
                 pub type blksize_t = i32;
                 pub type blkcnt_t = i64;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct stat {
+                #[derive(Copy, Clone)]
+                pub struct stat {
                     pub st_dev: dev_t,
                     pub st_mode: mode_t,
                     pub st_nlink: nlink_t,
@@ -2384,18 +2625,22 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct utimbuf {
+                #[derive(Copy, Clone)]
+                pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct pthread_attr_t {
+                #[derive(Copy)]
+                pub struct pthread_attr_t {
                     pub __sig: c_long,
-                    pub __opaque: [c_char; 36]
+                    pub __opaque: [c_char; 36],
                 }
                 impl ::core::clone::Clone for pthread_attr_t {
-                    fn clone(&self) -> pthread_attr_t { *self }
+                    fn clone(&self) -> pthread_attr_t {
+                        *self
+                    }
                 }
             }
             pub mod posix08 {
@@ -2404,7 +2649,8 @@ pub mod types {
             }
             pub mod extra {
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct mach_timebase_info {
+                #[derive(Copy, Clone)]
+                pub struct mach_timebase_info {
                     pub numer: u32,
                     pub denom: u32,
                 }
@@ -2457,7 +2703,7 @@ pub mod types {
             }
             pub mod posix01 {
                 use types::common::c99::{int32_t, int64_t};
-                use types::common::c99::{uint32_t};
+                use types::common::c99::uint32_t;
                 use types::os::arch::c95::{c_char, c_long, time_t};
                 use types::os::arch::posix88::{dev_t, gid_t, ino_t};
                 use types::os::arch::posix88::{mode_t, off_t, uid_t};
@@ -2467,7 +2713,8 @@ pub mod types {
                 pub type blkcnt_t = i64;
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct stat {
+                #[derive(Copy, Clone)]
+                pub struct stat {
                     pub st_dev: dev_t,
                     pub st_mode: mode_t,
                     pub st_nlink: nlink_t,
@@ -2493,18 +2740,22 @@ pub mod types {
                 }
 
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct utimbuf {
+                #[derive(Copy, Clone)]
+                pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct pthread_attr_t {
+                #[derive(Copy)]
+                pub struct pthread_attr_t {
                     pub __sig: c_long,
-                    pub __opaque: [c_char; 56]
+                    pub __opaque: [c_char; 56],
                 }
                 impl ::core::clone::Clone for pthread_attr_t {
-                    fn clone(&self) -> pthread_attr_t { *self }
+                    fn clone(&self) -> pthread_attr_t {
+                        *self
+                    }
                 }
             }
             pub mod posix08 {
@@ -2513,7 +2764,8 @@ pub mod types {
             }
             pub mod extra {
                 #[repr(C)]
-                #[derive(Copy, Clone)] pub struct mach_timebase_info {
+                #[derive(Copy, Clone)]
+                pub struct mach_timebase_info {
                     pub numer: u32,
                     pub denom: u32,
                 }
@@ -2533,21 +2785,21 @@ pub mod consts {
         pub mod c95 {
             use types::os::arch::c95::{c_int, c_uint};
 
-            pub const EXIT_FAILURE : c_int = 1;
-            pub const EXIT_SUCCESS : c_int = 0;
-            pub const RAND_MAX : c_int = 32767;
-            pub const EOF : c_int = -1;
-            pub const SEEK_SET : c_int = 0;
-            pub const SEEK_CUR : c_int = 1;
-            pub const SEEK_END : c_int = 2;
-            pub const _IOFBF : c_int = 0;
-            pub const _IONBF : c_int = 4;
-            pub const _IOLBF : c_int = 64;
-            pub const BUFSIZ : c_uint = 512;
-            pub const FOPEN_MAX : c_uint = 20;
-            pub const FILENAME_MAX : c_uint = 260;
-            pub const L_tmpnam : c_uint = 16;
-            pub const TMP_MAX : c_uint = 32767;
+            pub const EXIT_FAILURE: c_int = 1;
+            pub const EXIT_SUCCESS: c_int = 0;
+            pub const RAND_MAX: c_int = 32767;
+            pub const EOF: c_int = -1;
+            pub const SEEK_SET: c_int = 0;
+            pub const SEEK_CUR: c_int = 1;
+            pub const SEEK_END: c_int = 2;
+            pub const _IOFBF: c_int = 0;
+            pub const _IONBF: c_int = 4;
+            pub const _IOLBF: c_int = 64;
+            pub const BUFSIZ: c_uint = 512;
+            pub const FOPEN_MAX: c_uint = 20;
+            pub const FILENAME_MAX: c_uint = 260;
+            pub const L_tmpnam: c_uint = 16;
+            pub const TMP_MAX: c_uint = 32767;
 
             pub const WSAEINTR: c_int = 10004;
             pub const WSAEBADF: c_int = 10009;
@@ -2608,43 +2860,43 @@ pub mod consts {
             use types::os::arch::c95::c_int;
             use types::os::arch::posix88::mode_t;
 
-            pub const O_RDONLY : c_int = 0;
-            pub const O_WRONLY : c_int = 1;
-            pub const O_RDWR : c_int = 2;
-            pub const O_APPEND : c_int = 8;
-            pub const O_CREAT : c_int = 256;
-            pub const O_EXCL : c_int = 1024;
-            pub const O_TRUNC : c_int = 512;
-            pub const S_IFIFO : c_int = 4096;
-            pub const S_IFCHR : c_int = 8192;
-            pub const S_IFBLK : c_int = 12288;
-            pub const S_IFDIR : c_int = 16384;
-            pub const S_IFREG : c_int = 32768;
-            pub const S_IFLNK : c_int = 40960;
-            pub const S_IFSOCK : mode_t = 49152;
-            pub const S_IFMT : c_int = 61440;
-            pub const S_IEXEC : c_int = 64;
-            pub const S_IWRITE : c_int = 128;
-            pub const S_IREAD : c_int = 256;
-            pub const S_IRWXU : c_int = 448;
-            pub const S_IXUSR : c_int = 64;
-            pub const S_IWUSR : c_int = 128;
-            pub const S_IRUSR : c_int = 256;
-            pub const S_IRWXG : mode_t = 56;
-            pub const S_IXGRP : mode_t = 8;
-            pub const S_IWGRP : mode_t = 16;
-            pub const S_IRGRP : mode_t = 32;
-            pub const S_IRWXO : mode_t = 7;
-            pub const S_IXOTH : mode_t = 1;
-            pub const S_IWOTH : mode_t = 2;
-            pub const S_IROTH : mode_t = 4;
-            pub const F_OK : c_int = 0;
-            pub const R_OK : c_int = 4;
-            pub const W_OK : c_int = 2;
-            pub const X_OK : c_int = 1;
-            pub const STDIN_FILENO : c_int = 0;
-            pub const STDOUT_FILENO : c_int = 1;
-            pub const STDERR_FILENO : c_int = 2;
+            pub const O_RDONLY: c_int = 0;
+            pub const O_WRONLY: c_int = 1;
+            pub const O_RDWR: c_int = 2;
+            pub const O_APPEND: c_int = 8;
+            pub const O_CREAT: c_int = 256;
+            pub const O_EXCL: c_int = 1024;
+            pub const O_TRUNC: c_int = 512;
+            pub const S_IFIFO: c_int = 4096;
+            pub const S_IFCHR: c_int = 8192;
+            pub const S_IFBLK: c_int = 12288;
+            pub const S_IFDIR: c_int = 16384;
+            pub const S_IFREG: c_int = 32768;
+            pub const S_IFLNK: c_int = 40960;
+            pub const S_IFSOCK: mode_t = 49152;
+            pub const S_IFMT: c_int = 61440;
+            pub const S_IEXEC: c_int = 64;
+            pub const S_IWRITE: c_int = 128;
+            pub const S_IREAD: c_int = 256;
+            pub const S_IRWXU: c_int = 448;
+            pub const S_IXUSR: c_int = 64;
+            pub const S_IWUSR: c_int = 128;
+            pub const S_IRUSR: c_int = 256;
+            pub const S_IRWXG: mode_t = 56;
+            pub const S_IXGRP: mode_t = 8;
+            pub const S_IWGRP: mode_t = 16;
+            pub const S_IRGRP: mode_t = 32;
+            pub const S_IRWXO: mode_t = 7;
+            pub const S_IXOTH: mode_t = 1;
+            pub const S_IWOTH: mode_t = 2;
+            pub const S_IROTH: mode_t = 4;
+            pub const F_OK: c_int = 0;
+            pub const R_OK: c_int = 4;
+            pub const W_OK: c_int = 2;
+            pub const X_OK: c_int = 1;
+            pub const STDIN_FILENO: c_int = 0;
+            pub const STDOUT_FILENO: c_int = 1;
+            pub const STDERR_FILENO: c_int = 2;
         }
         pub mod posix01 {
         }
@@ -2702,121 +2954,121 @@ pub mod consts {
             use types::os::arch::c95::{c_int, c_long};
             use types::os::arch::extra::{WORD, DWORD, BOOL, HANDLE};
 
-            pub const TRUE : BOOL = 1;
-            pub const FALSE : BOOL = 0;
+            pub const TRUE: BOOL = 1;
+            pub const FALSE: BOOL = 0;
 
-            pub const O_TEXT : c_int = 16384;
-            pub const O_BINARY : c_int = 32768;
+            pub const O_TEXT: c_int = 16384;
+            pub const O_BINARY: c_int = 32768;
             pub const O_NOINHERIT: c_int = 128;
 
-            pub const ERROR_SUCCESS : c_int = 0;
+            pub const ERROR_SUCCESS: c_int = 0;
             pub const ERROR_INVALID_FUNCTION: c_int = 1;
             pub const ERROR_FILE_NOT_FOUND: c_int = 2;
             pub const ERROR_ACCESS_DENIED: c_int = 5;
-            pub const ERROR_INVALID_HANDLE : c_int = 6;
+            pub const ERROR_INVALID_HANDLE: c_int = 6;
             pub const ERROR_BROKEN_PIPE: c_int = 109;
-            pub const ERROR_DISK_FULL : c_int = 112;
-            pub const ERROR_CALL_NOT_IMPLEMENTED : c_int = 120;
-            pub const ERROR_INSUFFICIENT_BUFFER : c_int = 122;
-            pub const ERROR_INVALID_NAME : c_int = 123;
-            pub const ERROR_ALREADY_EXISTS : c_int = 183;
+            pub const ERROR_DISK_FULL: c_int = 112;
+            pub const ERROR_CALL_NOT_IMPLEMENTED: c_int = 120;
+            pub const ERROR_INSUFFICIENT_BUFFER: c_int = 122;
+            pub const ERROR_INVALID_NAME: c_int = 123;
+            pub const ERROR_ALREADY_EXISTS: c_int = 183;
             pub const ERROR_PIPE_BUSY: c_int = 231;
             pub const ERROR_NO_DATA: c_int = 232;
-            pub const ERROR_INVALID_ADDRESS : c_int = 487;
+            pub const ERROR_INVALID_ADDRESS: c_int = 487;
             pub const ERROR_PIPE_CONNECTED: c_int = 535;
             pub const ERROR_NOTHING_TO_TERMINATE: c_int = 758;
             pub const ERROR_OPERATION_ABORTED: c_int = 995;
             pub const ERROR_IO_PENDING: c_int = 997;
-            pub const ERROR_FILE_INVALID : c_int = 1006;
+            pub const ERROR_FILE_INVALID: c_int = 1006;
             pub const ERROR_NOT_FOUND: c_int = 1168;
             pub const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE;
 
-            pub const DELETE : DWORD = 0x00010000;
-            pub const READ_CONTROL : DWORD = 0x00020000;
-            pub const SYNCHRONIZE : DWORD = 0x00100000;
-            pub const WRITE_DAC : DWORD = 0x00040000;
-            pub const WRITE_OWNER : DWORD = 0x00080000;
-
-            pub const PROCESS_CREATE_PROCESS : DWORD = 0x0080;
-            pub const PROCESS_CREATE_THREAD : DWORD = 0x0002;
-            pub const PROCESS_DUP_HANDLE : DWORD = 0x0040;
-            pub const PROCESS_QUERY_INFORMATION : DWORD = 0x0400;
-            pub const PROCESS_QUERY_LIMITED_INFORMATION : DWORD = 0x1000;
-            pub const PROCESS_SET_INFORMATION : DWORD = 0x0200;
-            pub const PROCESS_SET_QUOTA : DWORD = 0x0100;
-            pub const PROCESS_SUSPEND_RESUME : DWORD = 0x0800;
-            pub const PROCESS_TERMINATE : DWORD = 0x0001;
-            pub const PROCESS_VM_OPERATION : DWORD = 0x0008;
-            pub const PROCESS_VM_READ : DWORD = 0x0010;
-            pub const PROCESS_VM_WRITE : DWORD = 0x0020;
-
-            pub const STARTF_FORCEONFEEDBACK : DWORD = 0x00000040;
-            pub const STARTF_FORCEOFFFEEDBACK : DWORD = 0x00000080;
-            pub const STARTF_PREVENTPINNING : DWORD = 0x00002000;
-            pub const STARTF_RUNFULLSCREEN : DWORD = 0x00000020;
-            pub const STARTF_TITLEISAPPID : DWORD = 0x00001000;
-            pub const STARTF_TITLEISLINKNAME : DWORD = 0x00000800;
-            pub const STARTF_USECOUNTCHARS : DWORD = 0x00000008;
-            pub const STARTF_USEFILLATTRIBUTE : DWORD = 0x00000010;
-            pub const STARTF_USEHOTKEY : DWORD = 0x00000200;
-            pub const STARTF_USEPOSITION : DWORD = 0x00000004;
-            pub const STARTF_USESHOWWINDOW : DWORD = 0x00000001;
-            pub const STARTF_USESIZE : DWORD = 0x00000002;
-            pub const STARTF_USESTDHANDLES : DWORD = 0x00000100;
-
-            pub const WAIT_ABANDONED : DWORD = 0x00000080;
-            pub const WAIT_OBJECT_0 : DWORD = 0x00000000;
-            pub const WAIT_TIMEOUT : DWORD = 0x00000102;
-            pub const WAIT_FAILED : DWORD = !0;
-
-            pub const DUPLICATE_CLOSE_SOURCE : DWORD = 0x00000001;
-            pub const DUPLICATE_SAME_ACCESS : DWORD = 0x00000002;
-
-            pub const INFINITE : DWORD = !0;
-            pub const STILL_ACTIVE : DWORD = 259;
-
-            pub const MEM_COMMIT : DWORD = 0x00001000;
-            pub const MEM_RESERVE : DWORD = 0x00002000;
-            pub const MEM_DECOMMIT : DWORD = 0x00004000;
-            pub const MEM_RELEASE : DWORD = 0x00008000;
-            pub const MEM_RESET : DWORD = 0x00080000;
-            pub const MEM_RESET_UNDO : DWORD = 0x1000000;
-            pub const MEM_LARGE_PAGES : DWORD = 0x20000000;
-            pub const MEM_PHYSICAL : DWORD = 0x00400000;
-            pub const MEM_TOP_DOWN : DWORD = 0x00100000;
-            pub const MEM_WRITE_WATCH : DWORD = 0x00200000;
-
-            pub const PAGE_EXECUTE : DWORD = 0x10;
-            pub const PAGE_EXECUTE_READ : DWORD = 0x20;
-            pub const PAGE_EXECUTE_READWRITE : DWORD = 0x40;
-            pub const PAGE_EXECUTE_WRITECOPY : DWORD = 0x80;
-            pub const PAGE_NOACCESS : DWORD = 0x01;
-            pub const PAGE_READONLY : DWORD = 0x02;
-            pub const PAGE_READWRITE : DWORD = 0x04;
-            pub const PAGE_WRITECOPY : DWORD = 0x08;
-            pub const PAGE_GUARD : DWORD = 0x100;
-            pub const PAGE_NOCACHE : DWORD = 0x200;
-            pub const PAGE_WRITECOMBINE : DWORD = 0x400;
-
-            pub const SEC_COMMIT : DWORD = 0x8000000;
-            pub const SEC_IMAGE : DWORD = 0x1000000;
-            pub const SEC_IMAGE_NO_EXECUTE : DWORD = 0x11000000;
-            pub const SEC_LARGE_PAGES : DWORD = 0x80000000;
-            pub const SEC_NOCACHE : DWORD = 0x10000000;
-            pub const SEC_RESERVE : DWORD = 0x4000000;
-            pub const SEC_WRITECOMBINE : DWORD = 0x40000000;
-
-            pub const FILE_MAP_ALL_ACCESS : DWORD = 0xf001f;
-            pub const FILE_MAP_READ : DWORD = 0x4;
-            pub const FILE_MAP_WRITE : DWORD = 0x2;
-            pub const FILE_MAP_COPY : DWORD = 0x1;
-            pub const FILE_MAP_EXECUTE : DWORD = 0x20;
-
-            pub const PROCESSOR_ARCHITECTURE_INTEL : WORD = 0;
-            pub const PROCESSOR_ARCHITECTURE_ARM : WORD = 5;
-            pub const PROCESSOR_ARCHITECTURE_IA64 : WORD = 6;
-            pub const PROCESSOR_ARCHITECTURE_AMD64 : WORD = 9;
-            pub const PROCESSOR_ARCHITECTURE_UNKNOWN : WORD = 0xffff;
+            pub const DELETE: DWORD = 0x00010000;
+            pub const READ_CONTROL: DWORD = 0x00020000;
+            pub const SYNCHRONIZE: DWORD = 0x00100000;
+            pub const WRITE_DAC: DWORD = 0x00040000;
+            pub const WRITE_OWNER: DWORD = 0x00080000;
+
+            pub const PROCESS_CREATE_PROCESS: DWORD = 0x0080;
+            pub const PROCESS_CREATE_THREAD: DWORD = 0x0002;
+            pub const PROCESS_DUP_HANDLE: DWORD = 0x0040;
+            pub const PROCESS_QUERY_INFORMATION: DWORD = 0x0400;
+            pub const PROCESS_QUERY_LIMITED_INFORMATION: DWORD = 0x1000;
+            pub const PROCESS_SET_INFORMATION: DWORD = 0x0200;
+            pub const PROCESS_SET_QUOTA: DWORD = 0x0100;
+            pub const PROCESS_SUSPEND_RESUME: DWORD = 0x0800;
+            pub const PROCESS_TERMINATE: DWORD = 0x0001;
+            pub const PROCESS_VM_OPERATION: DWORD = 0x0008;
+            pub const PROCESS_VM_READ: DWORD = 0x0010;
+            pub const PROCESS_VM_WRITE: DWORD = 0x0020;
+
+            pub const STARTF_FORCEONFEEDBACK: DWORD = 0x00000040;
+            pub const STARTF_FORCEOFFFEEDBACK: DWORD = 0x00000080;
+            pub const STARTF_PREVENTPINNING: DWORD = 0x00002000;
+            pub const STARTF_RUNFULLSCREEN: DWORD = 0x00000020;
+            pub const STARTF_TITLEISAPPID: DWORD = 0x00001000;
+            pub const STARTF_TITLEISLINKNAME: DWORD = 0x00000800;
+            pub const STARTF_USECOUNTCHARS: DWORD = 0x00000008;
+            pub const STARTF_USEFILLATTRIBUTE: DWORD = 0x00000010;
+            pub const STARTF_USEHOTKEY: DWORD = 0x00000200;
+            pub const STARTF_USEPOSITION: DWORD = 0x00000004;
+            pub const STARTF_USESHOWWINDOW: DWORD = 0x00000001;
+            pub const STARTF_USESIZE: DWORD = 0x00000002;
+            pub const STARTF_USESTDHANDLES: DWORD = 0x00000100;
+
+            pub const WAIT_ABANDONED: DWORD = 0x00000080;
+            pub const WAIT_OBJECT_0: DWORD = 0x00000000;
+            pub const WAIT_TIMEOUT: DWORD = 0x00000102;
+            pub const WAIT_FAILED: DWORD = !0;
+
+            pub const DUPLICATE_CLOSE_SOURCE: DWORD = 0x00000001;
+            pub const DUPLICATE_SAME_ACCESS: DWORD = 0x00000002;
+
+            pub const INFINITE: DWORD = !0;
+            pub const STILL_ACTIVE: DWORD = 259;
+
+            pub const MEM_COMMIT: DWORD = 0x00001000;
+            pub const MEM_RESERVE: DWORD = 0x00002000;
+            pub const MEM_DECOMMIT: DWORD = 0x00004000;
+            pub const MEM_RELEASE: DWORD = 0x00008000;
+            pub const MEM_RESET: DWORD = 0x00080000;
+            pub const MEM_RESET_UNDO: DWORD = 0x1000000;
+            pub const MEM_LARGE_PAGES: DWORD = 0x20000000;
+            pub const MEM_PHYSICAL: DWORD = 0x00400000;
+            pub const MEM_TOP_DOWN: DWORD = 0x00100000;
+            pub const MEM_WRITE_WATCH: DWORD = 0x00200000;
+
+            pub const PAGE_EXECUTE: DWORD = 0x10;
+            pub const PAGE_EXECUTE_READ: DWORD = 0x20;
+            pub const PAGE_EXECUTE_READWRITE: DWORD = 0x40;
+            pub const PAGE_EXECUTE_WRITECOPY: DWORD = 0x80;
+            pub const PAGE_NOACCESS: DWORD = 0x01;
+            pub const PAGE_READONLY: DWORD = 0x02;
+            pub const PAGE_READWRITE: DWORD = 0x04;
+            pub const PAGE_WRITECOPY: DWORD = 0x08;
+            pub const PAGE_GUARD: DWORD = 0x100;
+            pub const PAGE_NOCACHE: DWORD = 0x200;
+            pub const PAGE_WRITECOMBINE: DWORD = 0x400;
+
+            pub const SEC_COMMIT: DWORD = 0x8000000;
+            pub const SEC_IMAGE: DWORD = 0x1000000;
+            pub const SEC_IMAGE_NO_EXECUTE: DWORD = 0x11000000;
+            pub const SEC_LARGE_PAGES: DWORD = 0x80000000;
+            pub const SEC_NOCACHE: DWORD = 0x10000000;
+            pub const SEC_RESERVE: DWORD = 0x4000000;
+            pub const SEC_WRITECOMBINE: DWORD = 0x40000000;
+
+            pub const FILE_MAP_ALL_ACCESS: DWORD = 0xf001f;
+            pub const FILE_MAP_READ: DWORD = 0x4;
+            pub const FILE_MAP_WRITE: DWORD = 0x2;
+            pub const FILE_MAP_COPY: DWORD = 0x1;
+            pub const FILE_MAP_EXECUTE: DWORD = 0x20;
+
+            pub const PROCESSOR_ARCHITECTURE_INTEL: WORD = 0;
+            pub const PROCESSOR_ARCHITECTURE_ARM: WORD = 5;
+            pub const PROCESSOR_ARCHITECTURE_IA64: WORD = 6;
+            pub const PROCESSOR_ARCHITECTURE_AMD64: WORD = 9;
+            pub const PROCESSOR_ARCHITECTURE_UNKNOWN: WORD = 0xffff;
 
             pub const MOVEFILE_COPY_ALLOWED: DWORD = 2;
             pub const MOVEFILE_CREATE_HARDLINK: DWORD = 16;
@@ -2891,13 +3143,15 @@ pub mod consts {
             pub const STANDARD_RIGHTS_WRITE: DWORD = 0x20000;
             pub const FILE_WRITE_EA: DWORD = 0x00000010;
             pub const FILE_READ_EA: DWORD = 0x00000008;
-            pub const FILE_GENERIC_READ: DWORD =
-                STANDARD_RIGHTS_READ | FILE_READ_DATA |
-                FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE;
-            pub const FILE_GENERIC_WRITE: DWORD =
-                STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA |
-                FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA |
-                SYNCHRONIZE;
+            pub const FILE_GENERIC_READ: DWORD = STANDARD_RIGHTS_READ | FILE_READ_DATA |
+                                                 FILE_READ_ATTRIBUTES |
+                                                 FILE_READ_EA |
+                                                 SYNCHRONIZE;
+            pub const FILE_GENERIC_WRITE: DWORD = STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA |
+                                                  FILE_WRITE_ATTRIBUTES |
+                                                  FILE_WRITE_EA |
+                                                  FILE_APPEND_DATA |
+                                                  SYNCHRONIZE;
 
             pub const FILE_BEGIN: DWORD = 0;
             pub const FILE_CURRENT: DWORD = 1;
@@ -2938,21 +3192,21 @@ pub mod consts {
         pub mod c95 {
             use types::os::arch::c95::{c_int, c_uint};
 
-            pub const EXIT_FAILURE : c_int = 1;
-            pub const EXIT_SUCCESS : c_int = 0;
-            pub const RAND_MAX : c_int = 2147483647;
-            pub const EOF : c_int = -1;
-            pub const SEEK_SET : c_int = 0;
-            pub const SEEK_CUR : c_int = 1;
-            pub const SEEK_END : c_int = 2;
-            pub const _IOFBF : c_int = 0;
-            pub const _IONBF : c_int = 2;
-            pub const _IOLBF : c_int = 1;
-            pub const BUFSIZ : c_uint = 8192;
-            pub const FOPEN_MAX : c_uint = 16;
-            pub const FILENAME_MAX : c_uint = 4096;
-            pub const L_tmpnam : c_uint = 20;
-            pub const TMP_MAX : c_uint = 238328;
+            pub const EXIT_FAILURE: c_int = 1;
+            pub const EXIT_SUCCESS: c_int = 0;
+            pub const RAND_MAX: c_int = 2147483647;
+            pub const EOF: c_int = -1;
+            pub const SEEK_SET: c_int = 0;
+            pub const SEEK_CUR: c_int = 1;
+            pub const SEEK_END: c_int = 2;
+            pub const _IOFBF: c_int = 0;
+            pub const _IONBF: c_int = 2;
+            pub const _IOLBF: c_int = 1;
+            pub const BUFSIZ: c_uint = 8192;
+            pub const FOPEN_MAX: c_uint = 16;
+            pub const FILENAME_MAX: c_uint = 4096;
+            pub const L_tmpnam: c_uint = 20;
+            pub const TMP_MAX: c_uint = 238328;
         }
         pub mod c99 {
         }
@@ -2967,114 +3221,114 @@ pub mod consts {
             use types::common::c95::c_void;
             use types::os::arch::posix88::mode_t;
 
-            pub const O_RDONLY : c_int = 0;
-            pub const O_WRONLY : c_int = 1;
-            pub const O_RDWR : c_int = 2;
-            pub const O_APPEND : c_int = 1024;
-            pub const O_CREAT : c_int = 64;
-            pub const O_EXCL : c_int = 128;
-            pub const O_NOCTTY : c_int = 256;
-            pub const O_TRUNC : c_int = 512;
-            pub const S_IFIFO : mode_t = 4096;
-            pub const S_IFCHR : mode_t = 8192;
-            pub const S_IFBLK : mode_t = 24576;
-            pub const S_IFDIR : mode_t = 16384;
-            pub const S_IFREG : mode_t = 32768;
-            pub const S_IFLNK : mode_t = 40960;
-            pub const S_IFSOCK : mode_t = 49152;
-            pub const S_IFMT : mode_t = 61440;
-            pub const S_IEXEC : mode_t = 64;
-            pub const S_IWRITE : mode_t = 128;
-            pub const S_IREAD : mode_t = 256;
-            pub const S_IRWXU : mode_t = 448;
-            pub const S_IXUSR : mode_t = 64;
-            pub const S_IWUSR : mode_t = 128;
-            pub const S_IRUSR : mode_t = 256;
-            pub const S_IRWXG : mode_t = 56;
-            pub const S_IXGRP : mode_t = 8;
-            pub const S_IWGRP : mode_t = 16;
-            pub const S_IRGRP : mode_t = 32;
-            pub const S_IRWXO : mode_t = 7;
-            pub const S_IXOTH : mode_t = 1;
-            pub const S_IWOTH : mode_t = 2;
-            pub const S_IROTH : mode_t = 4;
-            pub const F_OK : c_int = 0;
-            pub const R_OK : c_int = 4;
-            pub const W_OK : c_int = 2;
-            pub const X_OK : c_int = 1;
-            pub const STDIN_FILENO : c_int = 0;
-            pub const STDOUT_FILENO : c_int = 1;
-            pub const STDERR_FILENO : c_int = 2;
-            pub const F_LOCK : c_int = 1;
-            pub const F_TEST : c_int = 3;
-            pub const F_TLOCK : c_int = 2;
-            pub const F_ULOCK : c_int = 0;
-            pub const SIGHUP : c_int = 1;
-            pub const SIGINT : c_int = 2;
-            pub const SIGQUIT : c_int = 3;
-            pub const SIGILL : c_int = 4;
-            pub const SIGABRT : c_int = 6;
-            pub const SIGFPE : c_int = 8;
-            pub const SIGKILL : c_int = 9;
-            pub const SIGSEGV : c_int = 11;
-            pub const SIGPIPE : c_int = 13;
-            pub const SIGALRM : c_int = 14;
-            pub const SIGTERM : c_int = 15;
-
-            pub const PROT_NONE : c_int = 0;
-            pub const PROT_READ : c_int = 1;
-            pub const PROT_WRITE : c_int = 2;
-            pub const PROT_EXEC : c_int = 4;
-
-            pub const MAP_FILE : c_int = 0x0000;
-            pub const MAP_SHARED : c_int = 0x0001;
-            pub const MAP_PRIVATE : c_int = 0x0002;
-            pub const MAP_FIXED : c_int = 0x0010;
-            pub const MAP_ANON : c_int = 0x0020;
-
-            pub const MAP_FAILED : *mut c_void = !0 as *mut c_void;
-
-            pub const MCL_CURRENT : c_int = 0x0001;
-            pub const MCL_FUTURE : c_int = 0x0002;
-
-            pub const MS_ASYNC : c_int = 0x0001;
-            pub const MS_INVALIDATE : c_int = 0x0002;
-            pub const MS_SYNC : c_int = 0x0004;
-
-            pub const EPERM : c_int = 1;
-            pub const ENOENT : c_int = 2;
-            pub const ESRCH : c_int = 3;
-            pub const EINTR : c_int = 4;
-            pub const EIO : c_int = 5;
-            pub const ENXIO : c_int = 6;
-            pub const E2BIG : c_int = 7;
-            pub const ENOEXEC : c_int = 8;
-            pub const EBADF : c_int = 9;
-            pub const ECHILD : c_int = 10;
-            pub const EAGAIN : c_int = 11;
-            pub const ENOMEM : c_int = 12;
-            pub const EACCES : c_int = 13;
-            pub const EFAULT : c_int = 14;
-            pub const ENOTBLK : c_int = 15;
-            pub const EBUSY : c_int = 16;
-            pub const EEXIST : c_int = 17;
-            pub const EXDEV : c_int = 18;
-            pub const ENODEV : c_int = 19;
-            pub const ENOTDIR : c_int = 20;
-            pub const EISDIR : c_int = 21;
-            pub const EINVAL : c_int = 22;
-            pub const ENFILE : c_int = 23;
-            pub const EMFILE : c_int = 24;
-            pub const ENOTTY : c_int = 25;
-            pub const ETXTBSY : c_int = 26;
-            pub const EFBIG : c_int = 27;
-            pub const ENOSPC : c_int = 28;
-            pub const ESPIPE : c_int = 29;
-            pub const EROFS : c_int = 30;
-            pub const EMLINK : c_int = 31;
-            pub const EPIPE : c_int = 32;
-            pub const EDOM : c_int = 33;
-            pub const ERANGE : c_int = 34;
+            pub const O_RDONLY: c_int = 0;
+            pub const O_WRONLY: c_int = 1;
+            pub const O_RDWR: c_int = 2;
+            pub const O_APPEND: c_int = 1024;
+            pub const O_CREAT: c_int = 64;
+            pub const O_EXCL: c_int = 128;
+            pub const O_NOCTTY: c_int = 256;
+            pub const O_TRUNC: c_int = 512;
+            pub const S_IFIFO: mode_t = 4096;
+            pub const S_IFCHR: mode_t = 8192;
+            pub const S_IFBLK: mode_t = 24576;
+            pub const S_IFDIR: mode_t = 16384;
+            pub const S_IFREG: mode_t = 32768;
+            pub const S_IFLNK: mode_t = 40960;
+            pub const S_IFSOCK: mode_t = 49152;
+            pub const S_IFMT: mode_t = 61440;
+            pub const S_IEXEC: mode_t = 64;
+            pub const S_IWRITE: mode_t = 128;
+            pub const S_IREAD: mode_t = 256;
+            pub const S_IRWXU: mode_t = 448;
+            pub const S_IXUSR: mode_t = 64;
+            pub const S_IWUSR: mode_t = 128;
+            pub const S_IRUSR: mode_t = 256;
+            pub const S_IRWXG: mode_t = 56;
+            pub const S_IXGRP: mode_t = 8;
+            pub const S_IWGRP: mode_t = 16;
+            pub const S_IRGRP: mode_t = 32;
+            pub const S_IRWXO: mode_t = 7;
+            pub const S_IXOTH: mode_t = 1;
+            pub const S_IWOTH: mode_t = 2;
+            pub const S_IROTH: mode_t = 4;
+            pub const F_OK: c_int = 0;
+            pub const R_OK: c_int = 4;
+            pub const W_OK: c_int = 2;
+            pub const X_OK: c_int = 1;
+            pub const STDIN_FILENO: c_int = 0;
+            pub const STDOUT_FILENO: c_int = 1;
+            pub const STDERR_FILENO: c_int = 2;
+            pub const F_LOCK: c_int = 1;
+            pub const F_TEST: c_int = 3;
+            pub const F_TLOCK: c_int = 2;
+            pub const F_ULOCK: c_int = 0;
+            pub const SIGHUP: c_int = 1;
+            pub const SIGINT: c_int = 2;
+            pub const SIGQUIT: c_int = 3;
+            pub const SIGILL: c_int = 4;
+            pub const SIGABRT: c_int = 6;
+            pub const SIGFPE: c_int = 8;
+            pub const SIGKILL: c_int = 9;
+            pub const SIGSEGV: c_int = 11;
+            pub const SIGPIPE: c_int = 13;
+            pub const SIGALRM: c_int = 14;
+            pub const SIGTERM: c_int = 15;
+
+            pub const PROT_NONE: c_int = 0;
+            pub const PROT_READ: c_int = 1;
+            pub const PROT_WRITE: c_int = 2;
+            pub const PROT_EXEC: c_int = 4;
+
+            pub const MAP_FILE: c_int = 0x0000;
+            pub const MAP_SHARED: c_int = 0x0001;
+            pub const MAP_PRIVATE: c_int = 0x0002;
+            pub const MAP_FIXED: c_int = 0x0010;
+            pub const MAP_ANON: c_int = 0x0020;
+
+            pub const MAP_FAILED: *mut c_void = !0 as *mut c_void;
+
+            pub const MCL_CURRENT: c_int = 0x0001;
+            pub const MCL_FUTURE: c_int = 0x0002;
+
+            pub const MS_ASYNC: c_int = 0x0001;
+            pub const MS_INVALIDATE: c_int = 0x0002;
+            pub const MS_SYNC: c_int = 0x0004;
+
+            pub const EPERM: c_int = 1;
+            pub const ENOENT: c_int = 2;
+            pub const ESRCH: c_int = 3;
+            pub const EINTR: c_int = 4;
+            pub const EIO: c_int = 5;
+            pub const ENXIO: c_int = 6;
+            pub const E2BIG: c_int = 7;
+            pub const ENOEXEC: c_int = 8;
+            pub const EBADF: c_int = 9;
+            pub const ECHILD: c_int = 10;
+            pub const EAGAIN: c_int = 11;
+            pub const ENOMEM: c_int = 12;
+            pub const EACCES: c_int = 13;
+            pub const EFAULT: c_int = 14;
+            pub const ENOTBLK: c_int = 15;
+            pub const EBUSY: c_int = 16;
+            pub const EEXIST: c_int = 17;
+            pub const EXDEV: c_int = 18;
+            pub const ENODEV: c_int = 19;
+            pub const ENOTDIR: c_int = 20;
+            pub const EISDIR: c_int = 21;
+            pub const EINVAL: c_int = 22;
+            pub const ENFILE: c_int = 23;
+            pub const EMFILE: c_int = 24;
+            pub const ENOTTY: c_int = 25;
+            pub const ETXTBSY: c_int = 26;
+            pub const EFBIG: c_int = 27;
+            pub const ENOSPC: c_int = 28;
+            pub const ESPIPE: c_int = 29;
+            pub const EROFS: c_int = 30;
+            pub const EMLINK: c_int = 31;
+            pub const EPIPE: c_int = 32;
+            pub const EDOM: c_int = 33;
+            pub const ERANGE: c_int = 34;
 
             pub const EDEADLK: c_int = 35;
             pub const ENAMETOOLONG: c_int = 36;
@@ -3190,114 +3444,114 @@ pub mod consts {
             use types::common::c95::c_void;
             use types::os::arch::posix88::mode_t;
 
-            pub const O_RDONLY : c_int = 0;
-            pub const O_WRONLY : c_int = 1;
-            pub const O_RDWR : c_int = 2;
-            pub const O_APPEND : c_int = 8;
-            pub const O_CREAT : c_int = 256;
-            pub const O_EXCL : c_int = 1024;
-            pub const O_NOCTTY : c_int = 2048;
-            pub const O_TRUNC : c_int = 512;
-            pub const S_IFIFO : mode_t = 4096;
-            pub const S_IFCHR : mode_t = 8192;
-            pub const S_IFBLK : mode_t = 24576;
-            pub const S_IFDIR : mode_t = 16384;
-            pub const S_IFREG : mode_t = 32768;
-            pub const S_IFLNK : mode_t = 40960;
-            pub const S_IFSOCK : mode_t = 49152;
-            pub const S_IFMT : mode_t = 61440;
-            pub const S_IEXEC : mode_t = 64;
-            pub const S_IWRITE : mode_t = 128;
-            pub const S_IREAD : mode_t = 256;
-            pub const S_IRWXU : mode_t = 448;
-            pub const S_IXUSR : mode_t = 64;
-            pub const S_IWUSR : mode_t = 128;
-            pub const S_IRUSR : mode_t = 256;
-            pub const S_IRWXG : mode_t = 56;
-            pub const S_IXGRP : mode_t = 8;
-            pub const S_IWGRP : mode_t = 16;
-            pub const S_IRGRP : mode_t = 32;
-            pub const S_IRWXO : mode_t = 7;
-            pub const S_IXOTH : mode_t = 1;
-            pub const S_IWOTH : mode_t = 2;
-            pub const S_IROTH : mode_t = 4;
-            pub const F_OK : c_int = 0;
-            pub const R_OK : c_int = 4;
-            pub const W_OK : c_int = 2;
-            pub const X_OK : c_int = 1;
-            pub const STDIN_FILENO : c_int = 0;
-            pub const STDOUT_FILENO : c_int = 1;
-            pub const STDERR_FILENO : c_int = 2;
-            pub const F_LOCK : c_int = 1;
-            pub const F_TEST : c_int = 3;
-            pub const F_TLOCK : c_int = 2;
-            pub const F_ULOCK : c_int = 0;
-            pub const SIGHUP : c_int = 1;
-            pub const SIGINT : c_int = 2;
-            pub const SIGQUIT : c_int = 3;
-            pub const SIGILL : c_int = 4;
-            pub const SIGABRT : c_int = 6;
-            pub const SIGFPE : c_int = 8;
-            pub const SIGKILL : c_int = 9;
-            pub const SIGSEGV : c_int = 11;
-            pub const SIGPIPE : c_int = 13;
-            pub const SIGALRM : c_int = 14;
-            pub const SIGTERM : c_int = 15;
-
-            pub const PROT_NONE : c_int = 0;
-            pub const PROT_READ : c_int = 1;
-            pub const PROT_WRITE : c_int = 2;
-            pub const PROT_EXEC : c_int = 4;
-
-            pub const MAP_FILE : c_int = 0x0000;
-            pub const MAP_SHARED : c_int = 0x0001;
-            pub const MAP_PRIVATE : c_int = 0x0002;
-            pub const MAP_FIXED : c_int = 0x0010;
-            pub const MAP_ANON : c_int = 0x0800;
-
-            pub const MAP_FAILED : *mut c_void = !0 as *mut c_void;
-
-            pub const MCL_CURRENT : c_int = 0x0001;
-            pub const MCL_FUTURE : c_int = 0x0002;
-
-            pub const MS_ASYNC : c_int = 0x0001;
-            pub const MS_INVALIDATE : c_int = 0x0002;
-            pub const MS_SYNC : c_int = 0x0004;
-
-            pub const EPERM : c_int = 1;
-            pub const ENOENT : c_int = 2;
-            pub const ESRCH : c_int = 3;
-            pub const EINTR : c_int = 4;
-            pub const EIO : c_int = 5;
-            pub const ENXIO : c_int = 6;
-            pub const E2BIG : c_int = 7;
-            pub const ENOEXEC : c_int = 8;
-            pub const EBADF : c_int = 9;
-            pub const ECHILD : c_int = 10;
-            pub const EAGAIN : c_int = 11;
-            pub const ENOMEM : c_int = 12;
-            pub const EACCES : c_int = 13;
-            pub const EFAULT : c_int = 14;
-            pub const ENOTBLK : c_int = 15;
-            pub const EBUSY : c_int = 16;
-            pub const EEXIST : c_int = 17;
-            pub const EXDEV : c_int = 18;
-            pub const ENODEV : c_int = 19;
-            pub const ENOTDIR : c_int = 20;
-            pub const EISDIR : c_int = 21;
-            pub const EINVAL : c_int = 22;
-            pub const ENFILE : c_int = 23;
-            pub const EMFILE : c_int = 24;
-            pub const ENOTTY : c_int = 25;
-            pub const ETXTBSY : c_int = 26;
-            pub const EFBIG : c_int = 27;
-            pub const ENOSPC : c_int = 28;
-            pub const ESPIPE : c_int = 29;
-            pub const EROFS : c_int = 30;
-            pub const EMLINK : c_int = 31;
-            pub const EPIPE : c_int = 32;
-            pub const EDOM : c_int = 33;
-            pub const ERANGE : c_int = 34;
+            pub const O_RDONLY: c_int = 0;
+            pub const O_WRONLY: c_int = 1;
+            pub const O_RDWR: c_int = 2;
+            pub const O_APPEND: c_int = 8;
+            pub const O_CREAT: c_int = 256;
+            pub const O_EXCL: c_int = 1024;
+            pub const O_NOCTTY: c_int = 2048;
+            pub const O_TRUNC: c_int = 512;
+            pub const S_IFIFO: mode_t = 4096;
+            pub const S_IFCHR: mode_t = 8192;
+            pub const S_IFBLK: mode_t = 24576;
+            pub const S_IFDIR: mode_t = 16384;
+            pub const S_IFREG: mode_t = 32768;
+            pub const S_IFLNK: mode_t = 40960;
+            pub const S_IFSOCK: mode_t = 49152;
+            pub const S_IFMT: mode_t = 61440;
+            pub const S_IEXEC: mode_t = 64;
+            pub const S_IWRITE: mode_t = 128;
+            pub const S_IREAD: mode_t = 256;
+            pub const S_IRWXU: mode_t = 448;
+            pub const S_IXUSR: mode_t = 64;
+            pub const S_IWUSR: mode_t = 128;
+            pub const S_IRUSR: mode_t = 256;
+            pub const S_IRWXG: mode_t = 56;
+            pub const S_IXGRP: mode_t = 8;
+            pub const S_IWGRP: mode_t = 16;
+            pub const S_IRGRP: mode_t = 32;
+            pub const S_IRWXO: mode_t = 7;
+            pub const S_IXOTH: mode_t = 1;
+            pub const S_IWOTH: mode_t = 2;
+            pub const S_IROTH: mode_t = 4;
+            pub const F_OK: c_int = 0;
+            pub const R_OK: c_int = 4;
+            pub const W_OK: c_int = 2;
+            pub const X_OK: c_int = 1;
+            pub const STDIN_FILENO: c_int = 0;
+            pub const STDOUT_FILENO: c_int = 1;
+            pub const STDERR_FILENO: c_int = 2;
+            pub const F_LOCK: c_int = 1;
+            pub const F_TEST: c_int = 3;
+            pub const F_TLOCK: c_int = 2;
+            pub const F_ULOCK: c_int = 0;
+            pub const SIGHUP: c_int = 1;
+            pub const SIGINT: c_int = 2;
+            pub const SIGQUIT: c_int = 3;
+            pub const SIGILL: c_int = 4;
+            pub const SIGABRT: c_int = 6;
+            pub const SIGFPE: c_int = 8;
+            pub const SIGKILL: c_int = 9;
+            pub const SIGSEGV: c_int = 11;
+            pub const SIGPIPE: c_int = 13;
+            pub const SIGALRM: c_int = 14;
+            pub const SIGTERM: c_int = 15;
+
+            pub const PROT_NONE: c_int = 0;
+            pub const PROT_READ: c_int = 1;
+            pub const PROT_WRITE: c_int = 2;
+            pub const PROT_EXEC: c_int = 4;
+
+            pub const MAP_FILE: c_int = 0x0000;
+            pub const MAP_SHARED: c_int = 0x0001;
+            pub const MAP_PRIVATE: c_int = 0x0002;
+            pub const MAP_FIXED: c_int = 0x0010;
+            pub const MAP_ANON: c_int = 0x0800;
+
+            pub const MAP_FAILED: *mut c_void = !0 as *mut c_void;
+
+            pub const MCL_CURRENT: c_int = 0x0001;
+            pub const MCL_FUTURE: c_int = 0x0002;
+
+            pub const MS_ASYNC: c_int = 0x0001;
+            pub const MS_INVALIDATE: c_int = 0x0002;
+            pub const MS_SYNC: c_int = 0x0004;
+
+            pub const EPERM: c_int = 1;
+            pub const ENOENT: c_int = 2;
+            pub const ESRCH: c_int = 3;
+            pub const EINTR: c_int = 4;
+            pub const EIO: c_int = 5;
+            pub const ENXIO: c_int = 6;
+            pub const E2BIG: c_int = 7;
+            pub const ENOEXEC: c_int = 8;
+            pub const EBADF: c_int = 9;
+            pub const ECHILD: c_int = 10;
+            pub const EAGAIN: c_int = 11;
+            pub const ENOMEM: c_int = 12;
+            pub const EACCES: c_int = 13;
+            pub const EFAULT: c_int = 14;
+            pub const ENOTBLK: c_int = 15;
+            pub const EBUSY: c_int = 16;
+            pub const EEXIST: c_int = 17;
+            pub const EXDEV: c_int = 18;
+            pub const ENODEV: c_int = 19;
+            pub const ENOTDIR: c_int = 20;
+            pub const EISDIR: c_int = 21;
+            pub const EINVAL: c_int = 22;
+            pub const ENFILE: c_int = 23;
+            pub const EMFILE: c_int = 24;
+            pub const ENOTTY: c_int = 25;
+            pub const ETXTBSY: c_int = 26;
+            pub const EFBIG: c_int = 27;
+            pub const ENOSPC: c_int = 28;
+            pub const ESPIPE: c_int = 29;
+            pub const EROFS: c_int = 30;
+            pub const EMLINK: c_int = 31;
+            pub const EPIPE: c_int = 32;
+            pub const EDOM: c_int = 33;
+            pub const ERANGE: c_int = 34;
 
             pub const ENOMSG: c_int = 35;
             pub const EIDRM: c_int = 36;
@@ -3409,63 +3663,63 @@ pub mod consts {
             use types::os::arch::c95::{c_int, size_t};
             use types::os::common::posix01::rlim_t;
 
-            pub const F_DUPFD : c_int = 0;
-            pub const F_GETFD : c_int = 1;
-            pub const F_SETFD : c_int = 2;
-            pub const F_GETFL : c_int = 3;
-            pub const F_SETFL : c_int = 4;
+            pub const F_DUPFD: c_int = 0;
+            pub const F_GETFD: c_int = 1;
+            pub const F_SETFD: c_int = 2;
+            pub const F_GETFL: c_int = 3;
+            pub const F_SETFL: c_int = 4;
 
-            pub const O_ACCMODE : c_int = 3;
+            pub const O_ACCMODE: c_int = 3;
 
-            pub const SIGTRAP : c_int = 5;
+            pub const SIGTRAP: c_int = 5;
             pub const SIG_IGN: size_t = 1;
 
-            pub const GLOB_ERR      : c_int = 1 << 0;
-            pub const GLOB_MARK     : c_int = 1 << 1;
-            pub const GLOB_NOSORT   : c_int = 1 << 2;
-            pub const GLOB_DOOFFS   : c_int = 1 << 3;
-            pub const GLOB_NOCHECK  : c_int = 1 << 4;
-            pub const GLOB_APPEND   : c_int = 1 << 5;
-            pub const GLOB_NOESCAPE : c_int = 1 << 6;
-
-            pub const GLOB_NOSPACE  : c_int = 1;
-            pub const GLOB_ABORTED  : c_int = 2;
-            pub const GLOB_NOMATCH  : c_int = 3;
-
-            pub const POSIX_MADV_NORMAL : c_int = 0;
-            pub const POSIX_MADV_RANDOM : c_int = 1;
-            pub const POSIX_MADV_SEQUENTIAL : c_int = 2;
-            pub const POSIX_MADV_WILLNEED : c_int = 3;
-            pub const POSIX_MADV_DONTNEED : c_int = 4;
-
-            pub const _SC_MQ_PRIO_MAX : c_int = 28;
-            pub const _SC_IOV_MAX : c_int = 60;
-            pub const _SC_GETGR_R_SIZE_MAX : c_int = 69;
-            pub const _SC_GETPW_R_SIZE_MAX : c_int = 70;
-            pub const _SC_LOGIN_NAME_MAX : c_int = 71;
-            pub const _SC_TTY_NAME_MAX : c_int = 72;
-            pub const _SC_THREADS : c_int = 67;
-            pub const _SC_THREAD_SAFE_FUNCTIONS : c_int = 68;
-            pub const _SC_THREAD_DESTRUCTOR_ITERATIONS : c_int = 73;
-            pub const _SC_THREAD_KEYS_MAX : c_int = 74;
-            pub const _SC_THREAD_STACK_MIN : c_int = 75;
-            pub const _SC_THREAD_THREADS_MAX : c_int = 76;
-            pub const _SC_THREAD_ATTR_STACKADDR : c_int = 77;
-            pub const _SC_THREAD_ATTR_STACKSIZE : c_int = 78;
-            pub const _SC_THREAD_PRIORITY_SCHEDULING : c_int = 79;
-            pub const _SC_THREAD_PRIO_INHERIT : c_int = 80;
-            pub const _SC_THREAD_PRIO_PROTECT : c_int = 81;
-            pub const _SC_THREAD_PROCESS_SHARED : c_int = 82;
-            pub const _SC_ATEXIT_MAX : c_int = 87;
-            pub const _SC_XOPEN_VERSION : c_int = 89;
-            pub const _SC_XOPEN_XCU_VERSION : c_int = 90;
-            pub const _SC_XOPEN_UNIX : c_int = 91;
-            pub const _SC_XOPEN_CRYPT : c_int = 92;
-            pub const _SC_XOPEN_ENH_I18N : c_int = 93;
-            pub const _SC_XOPEN_SHM : c_int = 94;
-            pub const _SC_XOPEN_LEGACY : c_int = 129;
-            pub const _SC_XOPEN_REALTIME : c_int = 130;
-            pub const _SC_XOPEN_REALTIME_THREADS : c_int = 131;
+            pub const GLOB_ERR: c_int = 1 << 0;
+            pub const GLOB_MARK: c_int = 1 << 1;
+            pub const GLOB_NOSORT: c_int = 1 << 2;
+            pub const GLOB_DOOFFS: c_int = 1 << 3;
+            pub const GLOB_NOCHECK: c_int = 1 << 4;
+            pub const GLOB_APPEND: c_int = 1 << 5;
+            pub const GLOB_NOESCAPE: c_int = 1 << 6;
+
+            pub const GLOB_NOSPACE: c_int = 1;
+            pub const GLOB_ABORTED: c_int = 2;
+            pub const GLOB_NOMATCH: c_int = 3;
+
+            pub const POSIX_MADV_NORMAL: c_int = 0;
+            pub const POSIX_MADV_RANDOM: c_int = 1;
+            pub const POSIX_MADV_SEQUENTIAL: c_int = 2;
+            pub const POSIX_MADV_WILLNEED: c_int = 3;
+            pub const POSIX_MADV_DONTNEED: c_int = 4;
+
+            pub const _SC_MQ_PRIO_MAX: c_int = 28;
+            pub const _SC_IOV_MAX: c_int = 60;
+            pub const _SC_GETGR_R_SIZE_MAX: c_int = 69;
+            pub const _SC_GETPW_R_SIZE_MAX: c_int = 70;
+            pub const _SC_LOGIN_NAME_MAX: c_int = 71;
+            pub const _SC_TTY_NAME_MAX: c_int = 72;
+            pub const _SC_THREADS: c_int = 67;
+            pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 68;
+            pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 73;
+            pub const _SC_THREAD_KEYS_MAX: c_int = 74;
+            pub const _SC_THREAD_STACK_MIN: c_int = 75;
+            pub const _SC_THREAD_THREADS_MAX: c_int = 76;
+            pub const _SC_THREAD_ATTR_STACKADDR: c_int = 77;
+            pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 78;
+            pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 79;
+            pub const _SC_THREAD_PRIO_INHERIT: c_int = 80;
+            pub const _SC_THREAD_PRIO_PROTECT: c_int = 81;
+            pub const _SC_THREAD_PROCESS_SHARED: c_int = 82;
+            pub const _SC_ATEXIT_MAX: c_int = 87;
+            pub const _SC_XOPEN_VERSION: c_int = 89;
+            pub const _SC_XOPEN_XCU_VERSION: c_int = 90;
+            pub const _SC_XOPEN_UNIX: c_int = 91;
+            pub const _SC_XOPEN_CRYPT: c_int = 92;
+            pub const _SC_XOPEN_ENH_I18N: c_int = 93;
+            pub const _SC_XOPEN_SHM: c_int = 94;
+            pub const _SC_XOPEN_LEGACY: c_int = 129;
+            pub const _SC_XOPEN_REALTIME: c_int = 130;
+            pub const _SC_XOPEN_REALTIME_THREADS: c_int = 131;
 
 
 
@@ -3521,61 +3775,61 @@ pub mod consts {
             use types::os::arch::c95::{c_int, size_t};
             use types::os::common::posix01::rlim_t;
 
-            pub const F_DUPFD : c_int = 0;
-            pub const F_GETFD : c_int = 1;
-            pub const F_SETFD : c_int = 2;
-            pub const F_GETFL : c_int = 3;
-            pub const F_SETFL : c_int = 4;
+            pub const F_DUPFD: c_int = 0;
+            pub const F_GETFD: c_int = 1;
+            pub const F_SETFD: c_int = 2;
+            pub const F_GETFL: c_int = 3;
+            pub const F_SETFL: c_int = 4;
 
-            pub const SIGTRAP : c_int = 5;
+            pub const SIGTRAP: c_int = 5;
             pub const SIG_IGN: size_t = 1;
 
-            pub const GLOB_ERR      : c_int = 1 << 0;
-            pub const GLOB_MARK     : c_int = 1 << 1;
-            pub const GLOB_NOSORT   : c_int = 1 << 2;
-            pub const GLOB_DOOFFS   : c_int = 1 << 3;
-            pub const GLOB_NOCHECK  : c_int = 1 << 4;
-            pub const GLOB_APPEND   : c_int = 1 << 5;
-            pub const GLOB_NOESCAPE : c_int = 1 << 6;
-
-            pub const GLOB_NOSPACE  : c_int = 1;
-            pub const GLOB_ABORTED  : c_int = 2;
-            pub const GLOB_NOMATCH  : c_int = 3;
-
-            pub const POSIX_MADV_NORMAL : c_int = 0;
-            pub const POSIX_MADV_RANDOM : c_int = 1;
-            pub const POSIX_MADV_SEQUENTIAL : c_int = 2;
-            pub const POSIX_MADV_WILLNEED : c_int = 3;
-            pub const POSIX_MADV_DONTNEED : c_int = 4;
-
-            pub const _SC_MQ_PRIO_MAX : c_int = 28;
-            pub const _SC_IOV_MAX : c_int = 60;
-            pub const _SC_GETGR_R_SIZE_MAX : c_int = 69;
-            pub const _SC_GETPW_R_SIZE_MAX : c_int = 70;
-            pub const _SC_LOGIN_NAME_MAX : c_int = 71;
-            pub const _SC_TTY_NAME_MAX : c_int = 72;
-            pub const _SC_THREADS : c_int = 67;
-            pub const _SC_THREAD_SAFE_FUNCTIONS : c_int = 68;
-            pub const _SC_THREAD_DESTRUCTOR_ITERATIONS : c_int = 73;
-            pub const _SC_THREAD_KEYS_MAX : c_int = 74;
-            pub const _SC_THREAD_STACK_MIN : c_int = 75;
-            pub const _SC_THREAD_THREADS_MAX : c_int = 76;
-            pub const _SC_THREAD_ATTR_STACKADDR : c_int = 77;
-            pub const _SC_THREAD_ATTR_STACKSIZE : c_int = 78;
-            pub const _SC_THREAD_PRIORITY_SCHEDULING : c_int = 79;
-            pub const _SC_THREAD_PRIO_INHERIT : c_int = 80;
-            pub const _SC_THREAD_PRIO_PROTECT : c_int = 81;
-            pub const _SC_THREAD_PROCESS_SHARED : c_int = 82;
-            pub const _SC_ATEXIT_MAX : c_int = 87;
-            pub const _SC_XOPEN_VERSION : c_int = 89;
-            pub const _SC_XOPEN_XCU_VERSION : c_int = 90;
-            pub const _SC_XOPEN_UNIX : c_int = 91;
-            pub const _SC_XOPEN_CRYPT : c_int = 92;
-            pub const _SC_XOPEN_ENH_I18N : c_int = 93;
-            pub const _SC_XOPEN_SHM : c_int = 94;
-            pub const _SC_XOPEN_LEGACY : c_int = 129;
-            pub const _SC_XOPEN_REALTIME : c_int = 130;
-            pub const _SC_XOPEN_REALTIME_THREADS : c_int = 131;
+            pub const GLOB_ERR: c_int = 1 << 0;
+            pub const GLOB_MARK: c_int = 1 << 1;
+            pub const GLOB_NOSORT: c_int = 1 << 2;
+            pub const GLOB_DOOFFS: c_int = 1 << 3;
+            pub const GLOB_NOCHECK: c_int = 1 << 4;
+            pub const GLOB_APPEND: c_int = 1 << 5;
+            pub const GLOB_NOESCAPE: c_int = 1 << 6;
+
+            pub const GLOB_NOSPACE: c_int = 1;
+            pub const GLOB_ABORTED: c_int = 2;
+            pub const GLOB_NOMATCH: c_int = 3;
+
+            pub const POSIX_MADV_NORMAL: c_int = 0;
+            pub const POSIX_MADV_RANDOM: c_int = 1;
+            pub const POSIX_MADV_SEQUENTIAL: c_int = 2;
+            pub const POSIX_MADV_WILLNEED: c_int = 3;
+            pub const POSIX_MADV_DONTNEED: c_int = 4;
+
+            pub const _SC_MQ_PRIO_MAX: c_int = 28;
+            pub const _SC_IOV_MAX: c_int = 60;
+            pub const _SC_GETGR_R_SIZE_MAX: c_int = 69;
+            pub const _SC_GETPW_R_SIZE_MAX: c_int = 70;
+            pub const _SC_LOGIN_NAME_MAX: c_int = 71;
+            pub const _SC_TTY_NAME_MAX: c_int = 72;
+            pub const _SC_THREADS: c_int = 67;
+            pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 68;
+            pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 73;
+            pub const _SC_THREAD_KEYS_MAX: c_int = 74;
+            pub const _SC_THREAD_STACK_MIN: c_int = 75;
+            pub const _SC_THREAD_THREADS_MAX: c_int = 76;
+            pub const _SC_THREAD_ATTR_STACKADDR: c_int = 77;
+            pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 78;
+            pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 79;
+            pub const _SC_THREAD_PRIO_INHERIT: c_int = 80;
+            pub const _SC_THREAD_PRIO_PROTECT: c_int = 81;
+            pub const _SC_THREAD_PROCESS_SHARED: c_int = 82;
+            pub const _SC_ATEXIT_MAX: c_int = 87;
+            pub const _SC_XOPEN_VERSION: c_int = 89;
+            pub const _SC_XOPEN_XCU_VERSION: c_int = 90;
+            pub const _SC_XOPEN_UNIX: c_int = 91;
+            pub const _SC_XOPEN_CRYPT: c_int = 92;
+            pub const _SC_XOPEN_ENH_I18N: c_int = 93;
+            pub const _SC_XOPEN_SHM: c_int = 94;
+            pub const _SC_XOPEN_LEGACY: c_int = 129;
+            pub const _SC_XOPEN_REALTIME: c_int = 130;
+            pub const _SC_XOPEN_REALTIME_THREADS: c_int = 131;
 
             pub const PTHREAD_CREATE_JOINABLE: c_int = 1;
             pub const PTHREAD_CREATE_DETACHED: c_int = 0;
@@ -3625,17 +3879,17 @@ pub mod consts {
         pub mod bsd44 {
             use types::os::arch::c95::c_int;
 
-            pub const MADV_NORMAL : c_int = 0;
-            pub const MADV_RANDOM : c_int = 1;
-            pub const MADV_SEQUENTIAL : c_int = 2;
-            pub const MADV_WILLNEED : c_int = 3;
-            pub const MADV_DONTNEED : c_int = 4;
-            pub const MADV_REMOVE : c_int = 9;
-            pub const MADV_DONTFORK : c_int = 10;
-            pub const MADV_DOFORK : c_int = 11;
-            pub const MADV_MERGEABLE : c_int = 12;
-            pub const MADV_UNMERGEABLE : c_int = 13;
-            pub const MADV_HWPOISON : c_int = 100;
+            pub const MADV_NORMAL: c_int = 0;
+            pub const MADV_RANDOM: c_int = 1;
+            pub const MADV_SEQUENTIAL: c_int = 2;
+            pub const MADV_WILLNEED: c_int = 3;
+            pub const MADV_DONTNEED: c_int = 4;
+            pub const MADV_REMOVE: c_int = 9;
+            pub const MADV_DONTFORK: c_int = 10;
+            pub const MADV_DOFORK: c_int = 11;
+            pub const MADV_MERGEABLE: c_int = 12;
+            pub const MADV_UNMERGEABLE: c_int = 13;
+            pub const MADV_HWPOISON: c_int = 100;
 
             pub const IFF_LOOPBACK: c_int = 0x8;
 
@@ -3716,17 +3970,17 @@ pub mod consts {
         pub mod bsd44 {
             use types::os::arch::c95::c_int;
 
-            pub const MADV_NORMAL : c_int = 0;
-            pub const MADV_RANDOM : c_int = 1;
-            pub const MADV_SEQUENTIAL : c_int = 2;
-            pub const MADV_WILLNEED : c_int = 3;
-            pub const MADV_DONTNEED : c_int = 4;
-            pub const MADV_REMOVE : c_int = 9;
-            pub const MADV_DONTFORK : c_int = 10;
-            pub const MADV_DOFORK : c_int = 11;
-            pub const MADV_MERGEABLE : c_int = 12;
-            pub const MADV_UNMERGEABLE : c_int = 13;
-            pub const MADV_HWPOISON : c_int = 100;
+            pub const MADV_NORMAL: c_int = 0;
+            pub const MADV_RANDOM: c_int = 1;
+            pub const MADV_SEQUENTIAL: c_int = 2;
+            pub const MADV_WILLNEED: c_int = 3;
+            pub const MADV_DONTNEED: c_int = 4;
+            pub const MADV_REMOVE: c_int = 9;
+            pub const MADV_DONTFORK: c_int = 10;
+            pub const MADV_DOFORK: c_int = 11;
+            pub const MADV_MERGEABLE: c_int = 12;
+            pub const MADV_UNMERGEABLE: c_int = 13;
+            pub const MADV_HWPOISON: c_int = 100;
 
             pub const AF_UNIX: c_int = 1;
             pub const AF_INET: c_int = 2;
@@ -3809,117 +4063,121 @@ pub mod consts {
         pub mod extra {
             use types::os::arch::c95::c_int;
 
-            pub const AF_PACKET : c_int = 17;
-            pub const IPPROTO_RAW : c_int = 255;
-
-            pub const O_RSYNC : c_int = 1052672;
-            pub const O_DSYNC : c_int = 4096;
-            pub const O_NONBLOCK : c_int = 2048;
-            pub const O_SYNC : c_int = 1052672;
-
-            pub const PROT_GROWSDOWN : c_int = 0x010000000;
-            pub const PROT_GROWSUP : c_int = 0x020000000;
-
-            pub const MAP_TYPE : c_int = 0x000f;
-            pub const MAP_ANONYMOUS : c_int = 0x0020;
-            pub const MAP_32BIT : c_int = 0x0040;
-            pub const MAP_GROWSDOWN : c_int = 0x0100;
-            pub const MAP_DENYWRITE : c_int = 0x0800;
-            pub const MAP_EXECUTABLE : c_int = 0x01000;
-            pub const MAP_LOCKED : c_int = 0x02000;
-            pub const MAP_NORESERVE : c_int = 0x04000;
-            pub const MAP_POPULATE : c_int = 0x08000;
-            pub const MAP_NONBLOCK : c_int = 0x010000;
-            pub const MAP_STACK : c_int = 0x020000;
+            pub const AF_PACKET: c_int = 17;
+            pub const IPPROTO_RAW: c_int = 255;
+
+            pub const O_RSYNC: c_int = 1052672;
+            pub const O_DSYNC: c_int = 4096;
+            pub const O_NONBLOCK: c_int = 2048;
+            pub const O_SYNC: c_int = 1052672;
+
+            pub const PROT_GROWSDOWN: c_int = 0x010000000;
+            pub const PROT_GROWSUP: c_int = 0x020000000;
+
+            pub const MAP_TYPE: c_int = 0x000f;
+            pub const MAP_ANONYMOUS: c_int = 0x0020;
+            pub const MAP_32BIT: c_int = 0x0040;
+            pub const MAP_GROWSDOWN: c_int = 0x0100;
+            pub const MAP_DENYWRITE: c_int = 0x0800;
+            pub const MAP_EXECUTABLE: c_int = 0x01000;
+            pub const MAP_LOCKED: c_int = 0x02000;
+            pub const MAP_NORESERVE: c_int = 0x04000;
+            pub const MAP_POPULATE: c_int = 0x08000;
+            pub const MAP_NONBLOCK: c_int = 0x010000;
+            pub const MAP_STACK: c_int = 0x020000;
+
+            pub const PATH_MAX: c_int = 4096;
         }
         #[cfg(any(target_arch = "mips",
                   target_arch = "mipsel"))]
         pub mod extra {
             use types::os::arch::c95::c_int;
 
-            pub const AF_PACKET : c_int = 17;
-            pub const IPPROTO_RAW : c_int = 255;
-
-            pub const O_RSYNC : c_int = 16400;
-            pub const O_DSYNC : c_int = 16;
-            pub const O_NONBLOCK : c_int = 128;
-            pub const O_SYNC : c_int = 16400;
-
-            pub const PROT_GROWSDOWN : c_int = 0x01000000;
-            pub const PROT_GROWSUP : c_int = 0x02000000;
-
-            pub const MAP_TYPE : c_int = 0x000f;
-            pub const MAP_ANONYMOUS : c_int = 0x0800;
-            pub const MAP_GROWSDOWN : c_int = 0x01000;
-            pub const MAP_DENYWRITE : c_int = 0x02000;
-            pub const MAP_EXECUTABLE : c_int = 0x04000;
-            pub const MAP_LOCKED : c_int = 0x08000;
-            pub const MAP_NORESERVE : c_int = 0x0400;
-            pub const MAP_POPULATE : c_int = 0x010000;
-            pub const MAP_NONBLOCK : c_int = 0x020000;
-            pub const MAP_STACK : c_int = 0x040000;
+            pub const AF_PACKET: c_int = 17;
+            pub const IPPROTO_RAW: c_int = 255;
+
+            pub const O_RSYNC: c_int = 16400;
+            pub const O_DSYNC: c_int = 16;
+            pub const O_NONBLOCK: c_int = 128;
+            pub const O_SYNC: c_int = 16400;
+
+            pub const PROT_GROWSDOWN: c_int = 0x01000000;
+            pub const PROT_GROWSUP: c_int = 0x02000000;
+
+            pub const MAP_TYPE: c_int = 0x000f;
+            pub const MAP_ANONYMOUS: c_int = 0x0800;
+            pub const MAP_GROWSDOWN: c_int = 0x01000;
+            pub const MAP_DENYWRITE: c_int = 0x02000;
+            pub const MAP_EXECUTABLE: c_int = 0x04000;
+            pub const MAP_LOCKED: c_int = 0x08000;
+            pub const MAP_NORESERVE: c_int = 0x0400;
+            pub const MAP_POPULATE: c_int = 0x010000;
+            pub const MAP_NONBLOCK: c_int = 0x020000;
+            pub const MAP_STACK: c_int = 0x040000;
+
+            pub const PATH_MAX: c_int = 4096;
         }
         #[cfg(target_os = "linux")]
         pub mod sysconf {
             use types::os::arch::c95::c_int;
 
-            pub const _SC_ARG_MAX : c_int = 0;
-            pub const _SC_CHILD_MAX : c_int = 1;
-            pub const _SC_CLK_TCK : c_int = 2;
-            pub const _SC_NGROUPS_MAX : c_int = 3;
-            pub const _SC_OPEN_MAX : c_int = 4;
-            pub const _SC_STREAM_MAX : c_int = 5;
-            pub const _SC_TZNAME_MAX : c_int = 6;
-            pub const _SC_JOB_CONTROL : c_int = 7;
-            pub const _SC_SAVED_IDS : c_int = 8;
-            pub const _SC_REALTIME_SIGNALS : c_int = 9;
-            pub const _SC_PRIORITY_SCHEDULING : c_int = 10;
-            pub const _SC_TIMERS : c_int = 11;
-            pub const _SC_ASYNCHRONOUS_IO : c_int = 12;
-            pub const _SC_PRIORITIZED_IO : c_int = 13;
-            pub const _SC_SYNCHRONIZED_IO : c_int = 14;
-            pub const _SC_FSYNC : c_int = 15;
-            pub const _SC_MAPPED_FILES : c_int = 16;
-            pub const _SC_MEMLOCK : c_int = 17;
-            pub const _SC_MEMLOCK_RANGE : c_int = 18;
-            pub const _SC_MEMORY_PROTECTION : c_int = 19;
-            pub const _SC_MESSAGE_PASSING : c_int = 20;
-            pub const _SC_SEMAPHORES : c_int = 21;
-            pub const _SC_SHARED_MEMORY_OBJECTS : c_int = 22;
-            pub const _SC_AIO_LISTIO_MAX : c_int = 23;
-            pub const _SC_AIO_MAX : c_int = 24;
-            pub const _SC_AIO_PRIO_DELTA_MAX : c_int = 25;
-            pub const _SC_DELAYTIMER_MAX : c_int = 26;
-            pub const _SC_MQ_OPEN_MAX : c_int = 27;
-            pub const _SC_VERSION : c_int = 29;
-            pub const _SC_PAGESIZE : c_int = 30;
-            pub const _SC_RTSIG_MAX : c_int = 31;
-            pub const _SC_SEM_NSEMS_MAX : c_int = 32;
-            pub const _SC_SEM_VALUE_MAX : c_int = 33;
-            pub const _SC_SIGQUEUE_MAX : c_int = 34;
-            pub const _SC_TIMER_MAX : c_int = 35;
-            pub const _SC_BC_BASE_MAX : c_int = 36;
-            pub const _SC_BC_DIM_MAX : c_int = 37;
-            pub const _SC_BC_SCALE_MAX : c_int = 38;
-            pub const _SC_BC_STRING_MAX : c_int = 39;
-            pub const _SC_COLL_WEIGHTS_MAX : c_int = 40;
-            pub const _SC_EXPR_NEST_MAX : c_int = 42;
-            pub const _SC_LINE_MAX : c_int = 43;
-            pub const _SC_RE_DUP_MAX : c_int = 44;
-            pub const _SC_2_VERSION : c_int = 46;
-            pub const _SC_2_C_BIND : c_int = 47;
-            pub const _SC_2_C_DEV : c_int = 48;
-            pub const _SC_2_FORT_DEV : c_int = 49;
-            pub const _SC_2_FORT_RUN : c_int = 50;
-            pub const _SC_2_SW_DEV : c_int = 51;
-            pub const _SC_2_LOCALEDEF : c_int = 52;
-            pub const _SC_NPROCESSORS_ONLN : c_int = 84;
-            pub const _SC_2_CHAR_TERM : c_int = 95;
-            pub const _SC_2_C_VERSION : c_int = 96;
-            pub const _SC_2_UPE : c_int = 97;
-            pub const _SC_XBS5_ILP32_OFF32 : c_int = 125;
-            pub const _SC_XBS5_ILP32_OFFBIG : c_int = 126;
-            pub const _SC_XBS5_LPBIG_OFFBIG : c_int = 128;
+            pub const _SC_ARG_MAX: c_int = 0;
+            pub const _SC_CHILD_MAX: c_int = 1;
+            pub const _SC_CLK_TCK: c_int = 2;
+            pub const _SC_NGROUPS_MAX: c_int = 3;
+            pub const _SC_OPEN_MAX: c_int = 4;
+            pub const _SC_STREAM_MAX: c_int = 5;
+            pub const _SC_TZNAME_MAX: c_int = 6;
+            pub const _SC_JOB_CONTROL: c_int = 7;
+            pub const _SC_SAVED_IDS: c_int = 8;
+            pub const _SC_REALTIME_SIGNALS: c_int = 9;
+            pub const _SC_PRIORITY_SCHEDULING: c_int = 10;
+            pub const _SC_TIMERS: c_int = 11;
+            pub const _SC_ASYNCHRONOUS_IO: c_int = 12;
+            pub const _SC_PRIORITIZED_IO: c_int = 13;
+            pub const _SC_SYNCHRONIZED_IO: c_int = 14;
+            pub const _SC_FSYNC: c_int = 15;
+            pub const _SC_MAPPED_FILES: c_int = 16;
+            pub const _SC_MEMLOCK: c_int = 17;
+            pub const _SC_MEMLOCK_RANGE: c_int = 18;
+            pub const _SC_MEMORY_PROTECTION: c_int = 19;
+            pub const _SC_MESSAGE_PASSING: c_int = 20;
+            pub const _SC_SEMAPHORES: c_int = 21;
+            pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 22;
+            pub const _SC_AIO_LISTIO_MAX: c_int = 23;
+            pub const _SC_AIO_MAX: c_int = 24;
+            pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 25;
+            pub const _SC_DELAYTIMER_MAX: c_int = 26;
+            pub const _SC_MQ_OPEN_MAX: c_int = 27;
+            pub const _SC_VERSION: c_int = 29;
+            pub const _SC_PAGESIZE: c_int = 30;
+            pub const _SC_RTSIG_MAX: c_int = 31;
+            pub const _SC_SEM_NSEMS_MAX: c_int = 32;
+            pub const _SC_SEM_VALUE_MAX: c_int = 33;
+            pub const _SC_SIGQUEUE_MAX: c_int = 34;
+            pub const _SC_TIMER_MAX: c_int = 35;
+            pub const _SC_BC_BASE_MAX: c_int = 36;
+            pub const _SC_BC_DIM_MAX: c_int = 37;
+            pub const _SC_BC_SCALE_MAX: c_int = 38;
+            pub const _SC_BC_STRING_MAX: c_int = 39;
+            pub const _SC_COLL_WEIGHTS_MAX: c_int = 40;
+            pub const _SC_EXPR_NEST_MAX: c_int = 42;
+            pub const _SC_LINE_MAX: c_int = 43;
+            pub const _SC_RE_DUP_MAX: c_int = 44;
+            pub const _SC_2_VERSION: c_int = 46;
+            pub const _SC_2_C_BIND: c_int = 47;
+            pub const _SC_2_C_DEV: c_int = 48;
+            pub const _SC_2_FORT_DEV: c_int = 49;
+            pub const _SC_2_FORT_RUN: c_int = 50;
+            pub const _SC_2_SW_DEV: c_int = 51;
+            pub const _SC_2_LOCALEDEF: c_int = 52;
+            pub const _SC_NPROCESSORS_ONLN: c_int = 84;
+            pub const _SC_2_CHAR_TERM: c_int = 95;
+            pub const _SC_2_C_VERSION: c_int = 96;
+            pub const _SC_2_UPE: c_int = 97;
+            pub const _SC_XBS5_ILP32_OFF32: c_int = 125;
+            pub const _SC_XBS5_ILP32_OFFBIG: c_int = 126;
+            pub const _SC_XBS5_LPBIG_OFFBIG: c_int = 128;
 
             pub const _PC_NAME_MAX: c_int = 3;
             pub const _PC_PATH_MAX: c_int = 4;
@@ -3928,9 +4186,9 @@ pub mod consts {
         pub mod sysconf {
             use types::os::arch::c95::c_int;
 
-            pub static _SC_SENDMSG_MAX_SIZE : c_int = 0;
-            pub static _SC_NPROCESSORS_ONLN : c_int = 1;
-            pub static _SC_PAGESIZE : c_int = 2;
+            pub static _SC_SENDMSG_MAX_SIZE: c_int = 0;
+            pub static _SC_NPROCESSORS_ONLN: c_int = 1;
+            pub static _SC_PAGESIZE: c_int = 2;
 
             pub const _PC_NAME_MAX: c_int = 3;
             pub const _PC_PATH_MAX: c_int = 4;
@@ -3940,35 +4198,35 @@ pub mod consts {
         pub mod sysconf {
             use types::os::arch::c95::c_int;
 
-            pub const _SC_ARG_MAX : c_int = 0;
-            pub const _SC_BC_BASE_MAX : c_int = 1;
-            pub const _SC_BC_DIM_MAX : c_int = 2;
-            pub const _SC_BC_SCALE_MAX : c_int = 3;
-            pub const _SC_BC_STRING_MAX : c_int = 4;
-            pub const _SC_CHILD_MAX : c_int = 5;
-            pub const _SC_CLK_TCK : c_int = 6;
-            pub const _SC_COLL_WEIGHTS_MAX : c_int = 7;
-            pub const _SC_EXPR_NEST_MAX : c_int = 8;
-            pub const _SC_LINE_MAX : c_int = 9;
-            pub const _SC_NGROUPS_MAX : c_int = 10;
-            pub const _SC_OPEN_MAX : c_int = 11;
-            pub const _SC_2_C_BIND : c_int = 13;
-            pub const _SC_2_C_DEV : c_int = 14;
-            pub const _SC_2_C_VERSION : c_int = 15;
-            pub const _SC_2_CHAR_TERM : c_int = 16;
-            pub const _SC_2_FORT_DEV : c_int = 17;
-            pub const _SC_2_FORT_RUN : c_int = 18;
-            pub const _SC_2_LOCALEDEF : c_int = 19;
-            pub const _SC_2_SW_DEV : c_int = 20;
-            pub const _SC_2_UPE : c_int = 21;
-            pub const _SC_2_VERSION : c_int = 22;
-            pub const _SC_JOB_CONTROL : c_int = 23;
-            pub const _SC_SAVED_IDS : c_int = 24;
-            pub const _SC_VERSION : c_int = 25;
-            pub const _SC_RE_DUP_MAX : c_int = 26;
-            pub const _SC_STREAM_MAX : c_int = 27;
-            pub const _SC_TZNAME_MAX : c_int = 28;
-            pub const _SC_PAGESIZE : c_int = 39;
+            pub const _SC_ARG_MAX: c_int = 0;
+            pub const _SC_BC_BASE_MAX: c_int = 1;
+            pub const _SC_BC_DIM_MAX: c_int = 2;
+            pub const _SC_BC_SCALE_MAX: c_int = 3;
+            pub const _SC_BC_STRING_MAX: c_int = 4;
+            pub const _SC_CHILD_MAX: c_int = 5;
+            pub const _SC_CLK_TCK: c_int = 6;
+            pub const _SC_COLL_WEIGHTS_MAX: c_int = 7;
+            pub const _SC_EXPR_NEST_MAX: c_int = 8;
+            pub const _SC_LINE_MAX: c_int = 9;
+            pub const _SC_NGROUPS_MAX: c_int = 10;
+            pub const _SC_OPEN_MAX: c_int = 11;
+            pub const _SC_2_C_BIND: c_int = 13;
+            pub const _SC_2_C_DEV: c_int = 14;
+            pub const _SC_2_C_VERSION: c_int = 15;
+            pub const _SC_2_CHAR_TERM: c_int = 16;
+            pub const _SC_2_FORT_DEV: c_int = 17;
+            pub const _SC_2_FORT_RUN: c_int = 18;
+            pub const _SC_2_LOCALEDEF: c_int = 19;
+            pub const _SC_2_SW_DEV: c_int = 20;
+            pub const _SC_2_UPE: c_int = 21;
+            pub const _SC_2_VERSION: c_int = 22;
+            pub const _SC_JOB_CONTROL: c_int = 23;
+            pub const _SC_SAVED_IDS: c_int = 24;
+            pub const _SC_VERSION: c_int = 25;
+            pub const _SC_RE_DUP_MAX: c_int = 26;
+            pub const _SC_STREAM_MAX: c_int = 27;
+            pub const _SC_TZNAME_MAX: c_int = 28;
+            pub const _SC_PAGESIZE: c_int = 39;
 
             pub const _PC_NAME_MAX: c_int = 4;
             pub const _PC_PATH_MAX: c_int = 5;
@@ -3981,21 +4239,21 @@ pub mod consts {
         pub mod c95 {
             use types::os::arch::c95::{c_int, c_uint};
 
-            pub const EXIT_FAILURE : c_int = 1;
-            pub const EXIT_SUCCESS : c_int = 0;
-            pub const RAND_MAX : c_int = 2147483647;
-            pub const EOF : c_int = -1;
-            pub const SEEK_SET : c_int = 0;
-            pub const SEEK_CUR : c_int = 1;
-            pub const SEEK_END : c_int = 2;
-            pub const _IOFBF : c_int = 0;
-            pub const _IONBF : c_int = 2;
-            pub const _IOLBF : c_int = 1;
-            pub const BUFSIZ : c_uint = 1024;
-            pub const FOPEN_MAX : c_uint = 20;
-            pub const FILENAME_MAX : c_uint = 1024;
-            pub const L_tmpnam : c_uint = 1024;
-            pub const TMP_MAX : c_uint = 308915776;
+            pub const EXIT_FAILURE: c_int = 1;
+            pub const EXIT_SUCCESS: c_int = 0;
+            pub const RAND_MAX: c_int = 2147483647;
+            pub const EOF: c_int = -1;
+            pub const SEEK_SET: c_int = 0;
+            pub const SEEK_CUR: c_int = 1;
+            pub const SEEK_END: c_int = 2;
+            pub const _IOFBF: c_int = 0;
+            pub const _IONBF: c_int = 2;
+            pub const _IOLBF: c_int = 1;
+            pub const BUFSIZ: c_uint = 1024;
+            pub const FOPEN_MAX: c_uint = 20;
+            pub const FILENAME_MAX: c_uint = 1024;
+            pub const L_tmpnam: c_uint = 1024;
+            pub const TMP_MAX: c_uint = 308915776;
         }
         pub mod c99 {
         }
@@ -4004,241 +4262,241 @@ pub mod consts {
             use types::os::arch::c95::c_int;
             use types::os::arch::posix88::mode_t;
 
-            pub const O_RDONLY : c_int = 0;
-            pub const O_WRONLY : c_int = 1;
-            pub const O_RDWR : c_int = 2;
-            pub const O_APPEND : c_int = 8;
-            pub const O_CREAT : c_int = 512;
-            pub const O_EXCL : c_int = 2048;
-            pub const O_NOCTTY : c_int = 32768;
-            pub const O_TRUNC : c_int = 1024;
-            pub const S_IFIFO : mode_t = 4096;
-            pub const S_IFCHR : mode_t = 8192;
-            pub const S_IFBLK : mode_t = 24576;
-            pub const S_IFDIR : mode_t = 16384;
-            pub const S_IFREG : mode_t = 32768;
-            pub const S_IFLNK : mode_t = 40960;
-            pub const S_IFSOCK : mode_t = 49152;
-            pub const S_IFMT : mode_t = 61440;
-            pub const S_IEXEC : mode_t = 64;
-            pub const S_IWRITE : mode_t = 128;
-            pub const S_IREAD : mode_t = 256;
-            pub const S_IRWXU : mode_t = 448;
-            pub const S_IXUSR : mode_t = 64;
-            pub const S_IWUSR : mode_t = 128;
-            pub const S_IRUSR : mode_t = 256;
-            pub const S_IRWXG : mode_t = 56;
-            pub const S_IXGRP : mode_t = 8;
-            pub const S_IWGRP : mode_t = 16;
-            pub const S_IRGRP : mode_t = 32;
-            pub const S_IRWXO : mode_t = 7;
-            pub const S_IXOTH : mode_t = 1;
-            pub const S_IWOTH : mode_t = 2;
-            pub const S_IROTH : mode_t = 4;
-            pub const F_OK : c_int = 0;
-            pub const R_OK : c_int = 4;
-            pub const W_OK : c_int = 2;
-            pub const X_OK : c_int = 1;
-            pub const STDIN_FILENO : c_int = 0;
-            pub const STDOUT_FILENO : c_int = 1;
-            pub const STDERR_FILENO : c_int = 2;
-            pub const F_LOCK : c_int = 1;
-            pub const F_TEST : c_int = 3;
-            pub const F_TLOCK : c_int = 2;
-            pub const F_ULOCK : c_int = 0;
-            pub const SIGHUP : c_int = 1;
-            pub const SIGINT : c_int = 2;
-            pub const SIGQUIT : c_int = 3;
-            pub const SIGILL : c_int = 4;
-            pub const SIGABRT : c_int = 6;
-            pub const SIGFPE : c_int = 8;
-            pub const SIGKILL : c_int = 9;
-            pub const SIGSEGV : c_int = 11;
-            pub const SIGPIPE : c_int = 13;
-            pub const SIGALRM : c_int = 14;
-            pub const SIGTERM : c_int = 15;
-
-            pub const PROT_NONE : c_int = 0;
-            pub const PROT_READ : c_int = 1;
-            pub const PROT_WRITE : c_int = 2;
-            pub const PROT_EXEC : c_int = 4;
-
-            pub const MAP_FILE : c_int = 0x0000;
-            pub const MAP_SHARED : c_int = 0x0001;
-            pub const MAP_PRIVATE : c_int = 0x0002;
-            pub const MAP_FIXED : c_int = 0x0010;
-            pub const MAP_ANON : c_int = 0x1000;
-
-            pub const MAP_FAILED : *mut c_void = !0 as *mut c_void;
-
-            pub const MCL_CURRENT : c_int = 0x0001;
-            pub const MCL_FUTURE : c_int = 0x0002;
-
-            pub const MS_SYNC : c_int = 0x0000;
-            pub const MS_ASYNC : c_int = 0x0001;
-            pub const MS_INVALIDATE : c_int = 0x0002;
-
-            pub const EPERM : c_int = 1;
-            pub const ENOENT : c_int = 2;
-            pub const ESRCH : c_int = 3;
-            pub const EINTR : c_int = 4;
-            pub const EIO : c_int = 5;
-            pub const ENXIO : c_int = 6;
-            pub const E2BIG : c_int = 7;
-            pub const ENOEXEC : c_int = 8;
-            pub const EBADF : c_int = 9;
-            pub const ECHILD : c_int = 10;
-            pub const EDEADLK : c_int = 11;
-            pub const ENOMEM : c_int = 12;
-            pub const EACCES : c_int = 13;
-            pub const EFAULT : c_int = 14;
-            pub const ENOTBLK : c_int = 15;
-            pub const EBUSY : c_int = 16;
-            pub const EEXIST : c_int = 17;
-            pub const EXDEV : c_int = 18;
-            pub const ENODEV : c_int = 19;
-            pub const ENOTDIR : c_int = 20;
-            pub const EISDIR : c_int = 21;
-            pub const EINVAL : c_int = 22;
-            pub const ENFILE : c_int = 23;
-            pub const EMFILE : c_int = 24;
-            pub const ENOTTY : c_int = 25;
-            pub const ETXTBSY : c_int = 26;
-            pub const EFBIG : c_int = 27;
-            pub const ENOSPC : c_int = 28;
-            pub const ESPIPE : c_int = 29;
-            pub const EROFS : c_int = 30;
-            pub const EMLINK : c_int = 31;
-            pub const EPIPE : c_int = 32;
-            pub const EDOM : c_int = 33;
-            pub const ERANGE : c_int = 34;
-            pub const EAGAIN : c_int = 35;
-            pub const EWOULDBLOCK : c_int = 35;
-            pub const EINPROGRESS : c_int = 36;
-            pub const EALREADY : c_int = 37;
-            pub const ENOTSOCK : c_int = 38;
-            pub const EDESTADDRREQ : c_int = 39;
-            pub const EMSGSIZE : c_int = 40;
-            pub const EPROTOTYPE : c_int = 41;
-            pub const ENOPROTOOPT : c_int = 42;
-            pub const EPROTONOSUPPORT : c_int = 43;
-            pub const ESOCKTNOSUPPORT : c_int = 44;
-            pub const EOPNOTSUPP : c_int = 45;
-            pub const EPFNOSUPPORT : c_int = 46;
-            pub const EAFNOSUPPORT : c_int = 47;
-            pub const EADDRINUSE : c_int = 48;
-            pub const EADDRNOTAVAIL : c_int = 49;
-            pub const ENETDOWN : c_int = 50;
-            pub const ENETUNREACH : c_int = 51;
-            pub const ENETRESET : c_int = 52;
-            pub const ECONNABORTED : c_int = 53;
-            pub const ECONNRESET : c_int = 54;
-            pub const ENOBUFS : c_int = 55;
-            pub const EISCONN : c_int = 56;
-            pub const ENOTCONN : c_int = 57;
-            pub const ESHUTDOWN : c_int = 58;
-            pub const ETOOMANYREFS : c_int = 59;
-            pub const ETIMEDOUT : c_int = 60;
-            pub const ECONNREFUSED : c_int = 61;
-            pub const ELOOP : c_int = 62;
-            pub const ENAMETOOLONG : c_int = 63;
-            pub const EHOSTDOWN : c_int = 64;
-            pub const EHOSTUNREACH : c_int = 65;
-            pub const ENOTEMPTY : c_int = 66;
-            pub const EPROCLIM : c_int = 67;
-            pub const EUSERS : c_int = 68;
-            pub const EDQUOT : c_int = 69;
-            pub const ESTALE : c_int = 70;
-            pub const EREMOTE : c_int = 71;
-            pub const EBADRPC : c_int = 72;
-            pub const ERPCMISMATCH : c_int = 73;
-            pub const EPROGUNAVAIL : c_int = 74;
-            pub const EPROGMISMATCH : c_int = 75;
-            pub const EPROCUNAVAIL : c_int = 76;
-            pub const ENOLCK : c_int = 77;
-            pub const ENOSYS : c_int = 78;
-            pub const EFTYPE : c_int = 79;
-            pub const EAUTH : c_int = 80;
-            pub const ENEEDAUTH : c_int = 81;
-            pub const EIDRM : c_int = 82;
-            pub const ENOMSG : c_int = 83;
-            pub const EOVERFLOW : c_int = 84;
-            pub const ECANCELED : c_int = 85;
-            pub const EILSEQ : c_int = 86;
-            pub const ENOATTR : c_int = 87;
-            pub const EDOOFUS : c_int = 88;
-            pub const EBADMSG : c_int = 89;
-            pub const EMULTIHOP : c_int = 90;
-            pub const ENOLINK : c_int = 91;
-            pub const EPROTO : c_int = 92;
-            pub const ENOMEDIUM : c_int = 93;
-            pub const EUNUSED94 : c_int = 94;
-            pub const EUNUSED95 : c_int = 95;
-            pub const EUNUSED96 : c_int = 96;
-            pub const EUNUSED97 : c_int = 97;
-            pub const EUNUSED98 : c_int = 98;
-            pub const EASYNC : c_int = 99;
-            pub const ELAST : c_int = 99;
+            pub const O_RDONLY: c_int = 0;
+            pub const O_WRONLY: c_int = 1;
+            pub const O_RDWR: c_int = 2;
+            pub const O_APPEND: c_int = 8;
+            pub const O_CREAT: c_int = 512;
+            pub const O_EXCL: c_int = 2048;
+            pub const O_NOCTTY: c_int = 32768;
+            pub const O_TRUNC: c_int = 1024;
+            pub const S_IFIFO: mode_t = 4096;
+            pub const S_IFCHR: mode_t = 8192;
+            pub const S_IFBLK: mode_t = 24576;
+            pub const S_IFDIR: mode_t = 16384;
+            pub const S_IFREG: mode_t = 32768;
+            pub const S_IFLNK: mode_t = 40960;
+            pub const S_IFSOCK: mode_t = 49152;
+            pub const S_IFMT: mode_t = 61440;
+            pub const S_IEXEC: mode_t = 64;
+            pub const S_IWRITE: mode_t = 128;
+            pub const S_IREAD: mode_t = 256;
+            pub const S_IRWXU: mode_t = 448;
+            pub const S_IXUSR: mode_t = 64;
+            pub const S_IWUSR: mode_t = 128;
+            pub const S_IRUSR: mode_t = 256;
+            pub const S_IRWXG: mode_t = 56;
+            pub const S_IXGRP: mode_t = 8;
+            pub const S_IWGRP: mode_t = 16;
+            pub const S_IRGRP: mode_t = 32;
+            pub const S_IRWXO: mode_t = 7;
+            pub const S_IXOTH: mode_t = 1;
+            pub const S_IWOTH: mode_t = 2;
+            pub const S_IROTH: mode_t = 4;
+            pub const F_OK: c_int = 0;
+            pub const R_OK: c_int = 4;
+            pub const W_OK: c_int = 2;
+            pub const X_OK: c_int = 1;
+            pub const STDIN_FILENO: c_int = 0;
+            pub const STDOUT_FILENO: c_int = 1;
+            pub const STDERR_FILENO: c_int = 2;
+            pub const F_LOCK: c_int = 1;
+            pub const F_TEST: c_int = 3;
+            pub const F_TLOCK: c_int = 2;
+            pub const F_ULOCK: c_int = 0;
+            pub const SIGHUP: c_int = 1;
+            pub const SIGINT: c_int = 2;
+            pub const SIGQUIT: c_int = 3;
+            pub const SIGILL: c_int = 4;
+            pub const SIGABRT: c_int = 6;
+            pub const SIGFPE: c_int = 8;
+            pub const SIGKILL: c_int = 9;
+            pub const SIGSEGV: c_int = 11;
+            pub const SIGPIPE: c_int = 13;
+            pub const SIGALRM: c_int = 14;
+            pub const SIGTERM: c_int = 15;
+
+            pub const PROT_NONE: c_int = 0;
+            pub const PROT_READ: c_int = 1;
+            pub const PROT_WRITE: c_int = 2;
+            pub const PROT_EXEC: c_int = 4;
+
+            pub const MAP_FILE: c_int = 0x0000;
+            pub const MAP_SHARED: c_int = 0x0001;
+            pub const MAP_PRIVATE: c_int = 0x0002;
+            pub const MAP_FIXED: c_int = 0x0010;
+            pub const MAP_ANON: c_int = 0x1000;
+
+            pub const MAP_FAILED: *mut c_void = !0 as *mut c_void;
+
+            pub const MCL_CURRENT: c_int = 0x0001;
+            pub const MCL_FUTURE: c_int = 0x0002;
+
+            pub const MS_SYNC: c_int = 0x0000;
+            pub const MS_ASYNC: c_int = 0x0001;
+            pub const MS_INVALIDATE: c_int = 0x0002;
+
+            pub const EPERM: c_int = 1;
+            pub const ENOENT: c_int = 2;
+            pub const ESRCH: c_int = 3;
+            pub const EINTR: c_int = 4;
+            pub const EIO: c_int = 5;
+            pub const ENXIO: c_int = 6;
+            pub const E2BIG: c_int = 7;
+            pub const ENOEXEC: c_int = 8;
+            pub const EBADF: c_int = 9;
+            pub const ECHILD: c_int = 10;
+            pub const EDEADLK: c_int = 11;
+            pub const ENOMEM: c_int = 12;
+            pub const EACCES: c_int = 13;
+            pub const EFAULT: c_int = 14;
+            pub const ENOTBLK: c_int = 15;
+            pub const EBUSY: c_int = 16;
+            pub const EEXIST: c_int = 17;
+            pub const EXDEV: c_int = 18;
+            pub const ENODEV: c_int = 19;
+            pub const ENOTDIR: c_int = 20;
+            pub const EISDIR: c_int = 21;
+            pub const EINVAL: c_int = 22;
+            pub const ENFILE: c_int = 23;
+            pub const EMFILE: c_int = 24;
+            pub const ENOTTY: c_int = 25;
+            pub const ETXTBSY: c_int = 26;
+            pub const EFBIG: c_int = 27;
+            pub const ENOSPC: c_int = 28;
+            pub const ESPIPE: c_int = 29;
+            pub const EROFS: c_int = 30;
+            pub const EMLINK: c_int = 31;
+            pub const EPIPE: c_int = 32;
+            pub const EDOM: c_int = 33;
+            pub const ERANGE: c_int = 34;
+            pub const EAGAIN: c_int = 35;
+            pub const EWOULDBLOCK: c_int = 35;
+            pub const EINPROGRESS: c_int = 36;
+            pub const EALREADY: c_int = 37;
+            pub const ENOTSOCK: c_int = 38;
+            pub const EDESTADDRREQ: c_int = 39;
+            pub const EMSGSIZE: c_int = 40;
+            pub const EPROTOTYPE: c_int = 41;
+            pub const ENOPROTOOPT: c_int = 42;
+            pub const EPROTONOSUPPORT: c_int = 43;
+            pub const ESOCKTNOSUPPORT: c_int = 44;
+            pub const EOPNOTSUPP: c_int = 45;
+            pub const EPFNOSUPPORT: c_int = 46;
+            pub const EAFNOSUPPORT: c_int = 47;
+            pub const EADDRINUSE: c_int = 48;
+            pub const EADDRNOTAVAIL: c_int = 49;
+            pub const ENETDOWN: c_int = 50;
+            pub const ENETUNREACH: c_int = 51;
+            pub const ENETRESET: c_int = 52;
+            pub const ECONNABORTED: c_int = 53;
+            pub const ECONNRESET: c_int = 54;
+            pub const ENOBUFS: c_int = 55;
+            pub const EISCONN: c_int = 56;
+            pub const ENOTCONN: c_int = 57;
+            pub const ESHUTDOWN: c_int = 58;
+            pub const ETOOMANYREFS: c_int = 59;
+            pub const ETIMEDOUT: c_int = 60;
+            pub const ECONNREFUSED: c_int = 61;
+            pub const ELOOP: c_int = 62;
+            pub const ENAMETOOLONG: c_int = 63;
+            pub const EHOSTDOWN: c_int = 64;
+            pub const EHOSTUNREACH: c_int = 65;
+            pub const ENOTEMPTY: c_int = 66;
+            pub const EPROCLIM: c_int = 67;
+            pub const EUSERS: c_int = 68;
+            pub const EDQUOT: c_int = 69;
+            pub const ESTALE: c_int = 70;
+            pub const EREMOTE: c_int = 71;
+            pub const EBADRPC: c_int = 72;
+            pub const ERPCMISMATCH: c_int = 73;
+            pub const EPROGUNAVAIL: c_int = 74;
+            pub const EPROGMISMATCH: c_int = 75;
+            pub const EPROCUNAVAIL: c_int = 76;
+            pub const ENOLCK: c_int = 77;
+            pub const ENOSYS: c_int = 78;
+            pub const EFTYPE: c_int = 79;
+            pub const EAUTH: c_int = 80;
+            pub const ENEEDAUTH: c_int = 81;
+            pub const EIDRM: c_int = 82;
+            pub const ENOMSG: c_int = 83;
+            pub const EOVERFLOW: c_int = 84;
+            pub const ECANCELED: c_int = 85;
+            pub const EILSEQ: c_int = 86;
+            pub const ENOATTR: c_int = 87;
+            pub const EDOOFUS: c_int = 88;
+            pub const EBADMSG: c_int = 89;
+            pub const EMULTIHOP: c_int = 90;
+            pub const ENOLINK: c_int = 91;
+            pub const EPROTO: c_int = 92;
+            pub const ENOMEDIUM: c_int = 93;
+            pub const EUNUSED94: c_int = 94;
+            pub const EUNUSED95: c_int = 95;
+            pub const EUNUSED96: c_int = 96;
+            pub const EUNUSED97: c_int = 97;
+            pub const EUNUSED98: c_int = 98;
+            pub const EASYNC: c_int = 99;
+            pub const ELAST: c_int = 99;
         }
         pub mod posix01 {
             use types::os::arch::c95::{c_int, size_t};
             use types::os::common::posix01::rlim_t;
 
-            pub const F_DUPFD : c_int = 0;
-            pub const F_GETFD : c_int = 1;
-            pub const F_SETFD : c_int = 2;
-            pub const F_GETFL : c_int = 3;
-            pub const F_SETFL : c_int = 4;
+            pub const F_DUPFD: c_int = 0;
+            pub const F_GETFD: c_int = 1;
+            pub const F_SETFD: c_int = 2;
+            pub const F_GETFL: c_int = 3;
+            pub const F_SETFL: c_int = 4;
 
-            pub const SIGTRAP : c_int = 5;
+            pub const SIGTRAP: c_int = 5;
             pub const SIG_IGN: size_t = 1;
 
-            pub const GLOB_APPEND   : c_int = 0x0001;
-            pub const GLOB_DOOFFS   : c_int = 0x0002;
-            pub const GLOB_ERR      : c_int = 0x0004;
-            pub const GLOB_MARK     : c_int = 0x0008;
-            pub const GLOB_NOCHECK  : c_int = 0x0010;
-            pub const GLOB_NOSORT   : c_int = 0x0020;
-            pub const GLOB_NOESCAPE : c_int = 0x2000;
-
-            pub const GLOB_NOSPACE  : c_int = -1;
-            pub const GLOB_ABORTED  : c_int = -2;
-            pub const GLOB_NOMATCH  : c_int = -3;
-
-            pub const POSIX_MADV_NORMAL : c_int = 0;
-            pub const POSIX_MADV_RANDOM : c_int = 1;
-            pub const POSIX_MADV_SEQUENTIAL : c_int = 2;
-            pub const POSIX_MADV_WILLNEED : c_int = 3;
-            pub const POSIX_MADV_DONTNEED : c_int = 4;
-
-            pub const _SC_IOV_MAX : c_int = 56;
-            pub const _SC_GETGR_R_SIZE_MAX : c_int = 70;
-            pub const _SC_GETPW_R_SIZE_MAX : c_int = 71;
-            pub const _SC_LOGIN_NAME_MAX : c_int = 73;
-            pub const _SC_MQ_PRIO_MAX : c_int = 75;
-            pub const _SC_THREAD_ATTR_STACKADDR : c_int = 82;
-            pub const _SC_THREAD_ATTR_STACKSIZE : c_int = 83;
-            pub const _SC_THREAD_DESTRUCTOR_ITERATIONS : c_int = 85;
-            pub const _SC_THREAD_KEYS_MAX : c_int = 86;
-            pub const _SC_THREAD_PRIO_INHERIT : c_int = 87;
-            pub const _SC_THREAD_PRIO_PROTECT : c_int = 88;
-            pub const _SC_THREAD_PRIORITY_SCHEDULING : c_int = 89;
-            pub const _SC_THREAD_PROCESS_SHARED : c_int = 90;
-            pub const _SC_THREAD_SAFE_FUNCTIONS : c_int = 91;
-            pub const _SC_THREAD_STACK_MIN : c_int = 93;
-            pub const _SC_THREAD_THREADS_MAX : c_int = 94;
-            pub const _SC_THREADS : c_int = 96;
-            pub const _SC_TTY_NAME_MAX : c_int = 101;
-            pub const _SC_ATEXIT_MAX : c_int = 107;
-            pub const _SC_XOPEN_CRYPT : c_int = 108;
-            pub const _SC_XOPEN_ENH_I18N : c_int = 109;
-            pub const _SC_XOPEN_LEGACY : c_int = 110;
-            pub const _SC_XOPEN_REALTIME : c_int = 111;
-            pub const _SC_XOPEN_REALTIME_THREADS : c_int = 112;
-            pub const _SC_XOPEN_SHM : c_int = 113;
-            pub const _SC_XOPEN_UNIX : c_int = 115;
-            pub const _SC_XOPEN_VERSION : c_int = 116;
-            pub const _SC_XOPEN_XCU_VERSION : c_int = 117;
+            pub const GLOB_APPEND: c_int = 0x0001;
+            pub const GLOB_DOOFFS: c_int = 0x0002;
+            pub const GLOB_ERR: c_int = 0x0004;
+            pub const GLOB_MARK: c_int = 0x0008;
+            pub const GLOB_NOCHECK: c_int = 0x0010;
+            pub const GLOB_NOSORT: c_int = 0x0020;
+            pub const GLOB_NOESCAPE: c_int = 0x2000;
+
+            pub const GLOB_NOSPACE: c_int = -1;
+            pub const GLOB_ABORTED: c_int = -2;
+            pub const GLOB_NOMATCH: c_int = -3;
+
+            pub const POSIX_MADV_NORMAL: c_int = 0;
+            pub const POSIX_MADV_RANDOM: c_int = 1;
+            pub const POSIX_MADV_SEQUENTIAL: c_int = 2;
+            pub const POSIX_MADV_WILLNEED: c_int = 3;
+            pub const POSIX_MADV_DONTNEED: c_int = 4;
+
+            pub const _SC_IOV_MAX: c_int = 56;
+            pub const _SC_GETGR_R_SIZE_MAX: c_int = 70;
+            pub const _SC_GETPW_R_SIZE_MAX: c_int = 71;
+            pub const _SC_LOGIN_NAME_MAX: c_int = 73;
+            pub const _SC_MQ_PRIO_MAX: c_int = 75;
+            pub const _SC_THREAD_ATTR_STACKADDR: c_int = 82;
+            pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 83;
+            pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 85;
+            pub const _SC_THREAD_KEYS_MAX: c_int = 86;
+            pub const _SC_THREAD_PRIO_INHERIT: c_int = 87;
+            pub const _SC_THREAD_PRIO_PROTECT: c_int = 88;
+            pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 89;
+            pub const _SC_THREAD_PROCESS_SHARED: c_int = 90;
+            pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 91;
+            pub const _SC_THREAD_STACK_MIN: c_int = 93;
+            pub const _SC_THREAD_THREADS_MAX: c_int = 94;
+            pub const _SC_THREADS: c_int = 96;
+            pub const _SC_TTY_NAME_MAX: c_int = 101;
+            pub const _SC_ATEXIT_MAX: c_int = 107;
+            pub const _SC_XOPEN_CRYPT: c_int = 108;
+            pub const _SC_XOPEN_ENH_I18N: c_int = 109;
+            pub const _SC_XOPEN_LEGACY: c_int = 110;
+            pub const _SC_XOPEN_REALTIME: c_int = 111;
+            pub const _SC_XOPEN_REALTIME_THREADS: c_int = 112;
+            pub const _SC_XOPEN_SHM: c_int = 113;
+            pub const _SC_XOPEN_UNIX: c_int = 115;
+            pub const _SC_XOPEN_VERSION: c_int = 116;
+            pub const _SC_XOPEN_XCU_VERSION: c_int = 117;
 
             pub const PTHREAD_CREATE_JOINABLE: c_int = 0;
             pub const PTHREAD_CREATE_DETACHED: c_int = 1;
@@ -4297,24 +4555,24 @@ pub mod consts {
         pub mod bsd44 {
             use types::os::arch::c95::c_int;
 
-            pub const MADV_NORMAL : c_int = 0;
-            pub const MADV_RANDOM : c_int = 1;
-            pub const MADV_SEQUENTIAL : c_int = 2;
-            pub const MADV_WILLNEED : c_int = 3;
-            pub const MADV_DONTNEED : c_int = 4;
-            pub const MADV_FREE : c_int = 5;
-            pub const MADV_NOSYNC : c_int = 6;
-            pub const MADV_AUTOSYNC : c_int = 7;
-            pub const MADV_NOCORE : c_int = 8;
-            pub const MADV_CORE : c_int = 9;
-            pub const MADV_PROTECT : c_int = 10;
-
-            pub const MINCORE_INCORE : c_int =  0x1;
-            pub const MINCORE_REFERENCED : c_int = 0x2;
-            pub const MINCORE_MODIFIED : c_int = 0x4;
-            pub const MINCORE_REFERENCED_OTHER : c_int = 0x8;
-            pub const MINCORE_MODIFIED_OTHER : c_int = 0x10;
-            pub const MINCORE_SUPER : c_int = 0x20;
+            pub const MADV_NORMAL: c_int = 0;
+            pub const MADV_RANDOM: c_int = 1;
+            pub const MADV_SEQUENTIAL: c_int = 2;
+            pub const MADV_WILLNEED: c_int = 3;
+            pub const MADV_DONTNEED: c_int = 4;
+            pub const MADV_FREE: c_int = 5;
+            pub const MADV_NOSYNC: c_int = 6;
+            pub const MADV_AUTOSYNC: c_int = 7;
+            pub const MADV_NOCORE: c_int = 8;
+            pub const MADV_CORE: c_int = 9;
+            pub const MADV_PROTECT: c_int = 10;
+
+            pub const MINCORE_INCORE: c_int = 0x1;
+            pub const MINCORE_REFERENCED: c_int = 0x2;
+            pub const MINCORE_MODIFIED: c_int = 0x4;
+            pub const MINCORE_REFERENCED_OTHER: c_int = 0x8;
+            pub const MINCORE_MODIFIED_OTHER: c_int = 0x10;
+            pub const MINCORE_SUPER: c_int = 0x20;
 
             pub const AF_INET: c_int = 2;
             pub const AF_INET6: c_int = 28;
@@ -4370,8 +4628,8 @@ pub mod consts {
         pub mod extra {
             use types::os::arch::c95::c_int;
 
-            pub const O_SYNC : c_int = 128;
-            pub const O_NONBLOCK : c_int = 4;
+            pub const O_SYNC: c_int = 128;
+            pub const O_NONBLOCK: c_int = 4;
             pub const CTL_KERN: c_int = 1;
             pub const KERN_PROC: c_int = 14;
             #[cfg(target_os = "freebsd")]
@@ -4379,97 +4637,97 @@ pub mod consts {
             #[cfg(target_os = "dragonfly")]
             pub const KERN_PROC_PATHNAME: c_int = 9;
 
-            pub const MAP_COPY : c_int = 0x0002;
-            pub const MAP_RENAME : c_int = 0x0020;
-            pub const MAP_NORESERVE : c_int = 0x0040;
-            pub const MAP_HASSEMAPHORE : c_int = 0x0200;
-            pub const MAP_STACK : c_int = 0x0400;
-            pub const MAP_NOSYNC : c_int = 0x0800;
-            pub const MAP_NOCORE : c_int = 0x020000;
+            pub const MAP_COPY: c_int = 0x0002;
+            pub const MAP_RENAME: c_int = 0x0020;
+            pub const MAP_NORESERVE: c_int = 0x0040;
+            pub const MAP_HASSEMAPHORE: c_int = 0x0200;
+            pub const MAP_STACK: c_int = 0x0400;
+            pub const MAP_NOSYNC: c_int = 0x0800;
+            pub const MAP_NOCORE: c_int = 0x020000;
 
-            pub const IPPROTO_RAW : c_int = 255;
+            pub const IPPROTO_RAW: c_int = 255;
         }
         pub mod sysconf {
             use types::os::arch::c95::c_int;
 
-            pub const _SC_ARG_MAX : c_int = 1;
-            pub const _SC_CHILD_MAX : c_int = 2;
-            pub const _SC_CLK_TCK : c_int = 3;
-            pub const _SC_NGROUPS_MAX : c_int = 4;
-            pub const _SC_OPEN_MAX : c_int = 5;
-            pub const _SC_JOB_CONTROL : c_int = 6;
-            pub const _SC_SAVED_IDS : c_int = 7;
-            pub const _SC_VERSION : c_int = 8;
-            pub const _SC_BC_BASE_MAX : c_int = 9;
-            pub const _SC_BC_DIM_MAX : c_int = 10;
-            pub const _SC_BC_SCALE_MAX : c_int = 11;
-            pub const _SC_BC_STRING_MAX : c_int = 12;
-            pub const _SC_COLL_WEIGHTS_MAX : c_int = 13;
-            pub const _SC_EXPR_NEST_MAX : c_int = 14;
-            pub const _SC_LINE_MAX : c_int = 15;
-            pub const _SC_RE_DUP_MAX : c_int = 16;
-            pub const _SC_2_VERSION : c_int = 17;
-            pub const _SC_2_C_BIND : c_int = 18;
-            pub const _SC_2_C_DEV : c_int = 19;
-            pub const _SC_2_CHAR_TERM : c_int = 20;
-            pub const _SC_2_FORT_DEV : c_int = 21;
-            pub const _SC_2_FORT_RUN : c_int = 22;
-            pub const _SC_2_LOCALEDEF : c_int = 23;
-            pub const _SC_2_SW_DEV : c_int = 24;
-            pub const _SC_2_UPE : c_int = 25;
-            pub const _SC_STREAM_MAX : c_int = 26;
-            pub const _SC_TZNAME_MAX : c_int = 27;
-            pub const _SC_ASYNCHRONOUS_IO : c_int = 28;
-            pub const _SC_MAPPED_FILES : c_int = 29;
-            pub const _SC_MEMLOCK : c_int = 30;
-            pub const _SC_MEMLOCK_RANGE : c_int = 31;
-            pub const _SC_MEMORY_PROTECTION : c_int = 32;
-            pub const _SC_MESSAGE_PASSING : c_int = 33;
-            pub const _SC_PRIORITIZED_IO : c_int = 34;
-            pub const _SC_PRIORITY_SCHEDULING : c_int = 35;
-            pub const _SC_REALTIME_SIGNALS : c_int = 36;
-            pub const _SC_SEMAPHORES : c_int = 37;
-            pub const _SC_FSYNC : c_int = 38;
-            pub const _SC_SHARED_MEMORY_OBJECTS : c_int = 39;
-            pub const _SC_SYNCHRONIZED_IO : c_int = 40;
-            pub const _SC_TIMERS : c_int = 41;
-            pub const _SC_AIO_LISTIO_MAX : c_int = 42;
-            pub const _SC_AIO_MAX : c_int = 43;
-            pub const _SC_AIO_PRIO_DELTA_MAX : c_int = 44;
-            pub const _SC_DELAYTIMER_MAX : c_int = 45;
-            pub const _SC_MQ_OPEN_MAX : c_int = 46;
-            pub const _SC_PAGESIZE : c_int = 47;
-            pub const _SC_RTSIG_MAX : c_int = 48;
-            pub const _SC_SEM_NSEMS_MAX : c_int = 49;
-            pub const _SC_SEM_VALUE_MAX : c_int = 50;
-            pub const _SC_SIGQUEUE_MAX : c_int = 51;
-            pub const _SC_TIMER_MAX : c_int = 52;
+            pub const _SC_ARG_MAX: c_int = 1;
+            pub const _SC_CHILD_MAX: c_int = 2;
+            pub const _SC_CLK_TCK: c_int = 3;
+            pub const _SC_NGROUPS_MAX: c_int = 4;
+            pub const _SC_OPEN_MAX: c_int = 5;
+            pub const _SC_JOB_CONTROL: c_int = 6;
+            pub const _SC_SAVED_IDS: c_int = 7;
+            pub const _SC_VERSION: c_int = 8;
+            pub const _SC_BC_BASE_MAX: c_int = 9;
+            pub const _SC_BC_DIM_MAX: c_int = 10;
+            pub const _SC_BC_SCALE_MAX: c_int = 11;
+            pub const _SC_BC_STRING_MAX: c_int = 12;
+            pub const _SC_COLL_WEIGHTS_MAX: c_int = 13;
+            pub const _SC_EXPR_NEST_MAX: c_int = 14;
+            pub const _SC_LINE_MAX: c_int = 15;
+            pub const _SC_RE_DUP_MAX: c_int = 16;
+            pub const _SC_2_VERSION: c_int = 17;
+            pub const _SC_2_C_BIND: c_int = 18;
+            pub const _SC_2_C_DEV: c_int = 19;
+            pub const _SC_2_CHAR_TERM: c_int = 20;
+            pub const _SC_2_FORT_DEV: c_int = 21;
+            pub const _SC_2_FORT_RUN: c_int = 22;
+            pub const _SC_2_LOCALEDEF: c_int = 23;
+            pub const _SC_2_SW_DEV: c_int = 24;
+            pub const _SC_2_UPE: c_int = 25;
+            pub const _SC_STREAM_MAX: c_int = 26;
+            pub const _SC_TZNAME_MAX: c_int = 27;
+            pub const _SC_ASYNCHRONOUS_IO: c_int = 28;
+            pub const _SC_MAPPED_FILES: c_int = 29;
+            pub const _SC_MEMLOCK: c_int = 30;
+            pub const _SC_MEMLOCK_RANGE: c_int = 31;
+            pub const _SC_MEMORY_PROTECTION: c_int = 32;
+            pub const _SC_MESSAGE_PASSING: c_int = 33;
+            pub const _SC_PRIORITIZED_IO: c_int = 34;
+            pub const _SC_PRIORITY_SCHEDULING: c_int = 35;
+            pub const _SC_REALTIME_SIGNALS: c_int = 36;
+            pub const _SC_SEMAPHORES: c_int = 37;
+            pub const _SC_FSYNC: c_int = 38;
+            pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 39;
+            pub const _SC_SYNCHRONIZED_IO: c_int = 40;
+            pub const _SC_TIMERS: c_int = 41;
+            pub const _SC_AIO_LISTIO_MAX: c_int = 42;
+            pub const _SC_AIO_MAX: c_int = 43;
+            pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 44;
+            pub const _SC_DELAYTIMER_MAX: c_int = 45;
+            pub const _SC_MQ_OPEN_MAX: c_int = 46;
+            pub const _SC_PAGESIZE: c_int = 47;
+            pub const _SC_RTSIG_MAX: c_int = 48;
+            pub const _SC_SEM_NSEMS_MAX: c_int = 49;
+            pub const _SC_SEM_VALUE_MAX: c_int = 50;
+            pub const _SC_SIGQUEUE_MAX: c_int = 51;
+            pub const _SC_TIMER_MAX: c_int = 52;
 
             pub const _PC_NAME_MAX: c_int = 4;
             pub const _PC_PATH_MAX: c_int = 5;
         }
     }
 
-    #[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))]
+    #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
     pub mod os {
         pub mod c95 {
             use types::os::arch::c95::{c_int, c_uint};
 
-            pub const EXIT_FAILURE : c_int = 1;
-            pub const EXIT_SUCCESS : c_int = 0;
-            pub const RAND_MAX : c_int = 2147483647;
-            pub const EOF : c_int = -1;
-            pub const SEEK_SET : c_int = 0;
-            pub const SEEK_CUR : c_int = 1;
-            pub const SEEK_END : c_int = 2;
-            pub const _IOFBF : c_int = 0;
-            pub const _IONBF : c_int = 2;
-            pub const _IOLBF : c_int = 1;
-            pub const BUFSIZ : c_uint = 1024;
-            pub const FOPEN_MAX : c_uint = 20;
-            pub const FILENAME_MAX : c_uint = 1024;
-            pub const L_tmpnam : c_uint = 1024;
-            pub const TMP_MAX : c_uint = 308915776;
+            pub const EXIT_FAILURE: c_int = 1;
+            pub const EXIT_SUCCESS: c_int = 0;
+            pub const RAND_MAX: c_int = 2147483647;
+            pub const EOF: c_int = -1;
+            pub const SEEK_SET: c_int = 0;
+            pub const SEEK_CUR: c_int = 1;
+            pub const SEEK_END: c_int = 2;
+            pub const _IOFBF: c_int = 0;
+            pub const _IONBF: c_int = 2;
+            pub const _IOLBF: c_int = 1;
+            pub const BUFSIZ: c_uint = 1024;
+            pub const FOPEN_MAX: c_uint = 20;
+            pub const FILENAME_MAX: c_uint = 1024;
+            pub const L_tmpnam: c_uint = 1024;
+            pub const TMP_MAX: c_uint = 308915776;
         }
         pub mod c99 {
         }
@@ -4478,245 +4736,245 @@ pub mod consts {
             use types::os::arch::c95::c_int;
             use types::os::arch::posix88::mode_t;
 
-            pub const O_RDONLY : c_int = 0;
-            pub const O_WRONLY : c_int = 1;
-            pub const O_RDWR : c_int = 2;
-            pub const O_APPEND : c_int = 8;
-            pub const O_CREAT : c_int = 512;
-            pub const O_EXCL : c_int = 2048;
-            pub const O_NOCTTY : c_int = 32768;
-            pub const O_TRUNC : c_int = 1024;
-            pub const S_IFIFO : mode_t = 4096;
-            pub const S_IFCHR : mode_t = 8192;
-            pub const S_IFBLK : mode_t = 24576;
-            pub const S_IFDIR : mode_t = 16384;
-            pub const S_IFREG : mode_t = 32768;
-            pub const S_IFLNK : mode_t = 40960;
-            pub const S_IFSOCK : mode_t = 49152;
-            pub const S_IFMT : mode_t = 61440;
-            pub const S_IEXEC : mode_t = 64;
-            pub const S_IWRITE : mode_t = 128;
-            pub const S_IREAD : mode_t = 256;
-            pub const S_IRWXU : mode_t = 448;
-            pub const S_IXUSR : mode_t = 64;
-            pub const S_IWUSR : mode_t = 128;
-            pub const S_IRUSR : mode_t = 256;
-            pub const S_IRWXG : mode_t = 56;
-            pub const S_IXGRP : mode_t = 8;
-            pub const S_IWGRP : mode_t = 16;
-            pub const S_IRGRP : mode_t = 32;
-            pub const S_IRWXO : mode_t = 7;
-            pub const S_IXOTH : mode_t = 1;
-            pub const S_IWOTH : mode_t = 2;
-            pub const S_IROTH : mode_t = 4;
-            pub const F_OK : c_int = 0;
-            pub const R_OK : c_int = 4;
-            pub const W_OK : c_int = 2;
-            pub const X_OK : c_int = 1;
-            pub const STDIN_FILENO : c_int = 0;
-            pub const STDOUT_FILENO : c_int = 1;
-            pub const STDERR_FILENO : c_int = 2;
-            pub const F_LOCK : c_int = 1;
-            pub const F_TEST : c_int = 3;
-            pub const F_TLOCK : c_int = 2;
-            pub const F_ULOCK : c_int = 0;
-            pub const SIGHUP : c_int = 1;
-            pub const SIGINT : c_int = 2;
-            pub const SIGQUIT : c_int = 3;
-            pub const SIGILL : c_int = 4;
-            pub const SIGABRT : c_int = 6;
-            pub const SIGFPE : c_int = 8;
-            pub const SIGKILL : c_int = 9;
-            pub const SIGSEGV : c_int = 11;
-            pub const SIGPIPE : c_int = 13;
-            pub const SIGALRM : c_int = 14;
-            pub const SIGTERM : c_int = 15;
-
-            pub const PROT_NONE : c_int = 0;
-            pub const PROT_READ : c_int = 1;
-            pub const PROT_WRITE : c_int = 2;
-            pub const PROT_EXEC : c_int = 4;
-
-            pub const MAP_FILE : c_int = 0x0000;
-            pub const MAP_SHARED : c_int = 0x0001;
-            pub const MAP_PRIVATE : c_int = 0x0002;
-            pub const MAP_FIXED : c_int = 0x0010;
-            pub const MAP_ANON : c_int = 0x1000;
-
-            pub const MAP_FAILED : *mut c_void = !0 as *mut c_void;
-
-            pub const MCL_CURRENT : c_int = 0x0001;
-            pub const MCL_FUTURE : c_int = 0x0002;
-
-            pub const MS_ASYNC : c_int = 0x0001;
-            pub const MS_SYNC : c_int = 0x0002;
-            pub const MS_INVALIDATE : c_int = 0x0004;
-
-            pub const EPERM : c_int = 1;
-            pub const ENOENT : c_int = 2;
-            pub const ESRCH : c_int = 3;
-            pub const EINTR : c_int = 4;
-            pub const EIO : c_int = 5;
-            pub const ENXIO : c_int = 6;
-            pub const E2BIG : c_int = 7;
-            pub const ENOEXEC : c_int = 8;
-            pub const EBADF : c_int = 9;
-            pub const ECHILD : c_int = 10;
-            pub const EDEADLK : c_int = 11;
-            pub const ENOMEM : c_int = 12;
-            pub const EACCES : c_int = 13;
-            pub const EFAULT : c_int = 14;
-            pub const ENOTBLK : c_int = 15;
-            pub const EBUSY : c_int = 16;
-            pub const EEXIST : c_int = 17;
-            pub const EXDEV : c_int = 18;
-            pub const ENODEV : c_int = 19;
-            pub const ENOTDIR : c_int = 20;
-            pub const EISDIR : c_int = 21;
-            pub const EINVAL : c_int = 22;
-            pub const ENFILE : c_int = 23;
-            pub const EMFILE : c_int = 24;
-            pub const ENOTTY : c_int = 25;
-            pub const ETXTBSY : c_int = 26;
-            pub const EFBIG : c_int = 27;
-            pub const ENOSPC : c_int = 28;
-            pub const ESPIPE : c_int = 29;
-            pub const EROFS : c_int = 30;
-            pub const EMLINK : c_int = 31;
-            pub const EPIPE : c_int = 32;
-            pub const EDOM : c_int = 33;
-            pub const ERANGE : c_int = 34;
-            pub const EAGAIN : c_int = 35;
-            pub const EWOULDBLOCK : c_int = 35;
-            pub const EINPROGRESS : c_int = 36;
-            pub const EALREADY : c_int = 37;
-            pub const ENOTSOCK : c_int = 38;
-            pub const EDESTADDRREQ : c_int = 39;
-            pub const EMSGSIZE : c_int = 40;
-            pub const EPROTOTYPE : c_int = 41;
-            pub const ENOPROTOOPT : c_int = 42;
-            pub const EPROTONOSUPPORT : c_int = 43;
-            pub const ESOCKTNOSUPPORT : c_int = 44;
-            pub const EOPNOTSUPP : c_int = 45;
-            pub const EPFNOSUPPORT : c_int = 46;
-            pub const EAFNOSUPPORT : c_int = 47;
-            pub const EADDRINUSE : c_int = 48;
-            pub const EADDRNOTAVAIL : c_int = 49;
-            pub const ENETDOWN : c_int = 50;
-            pub const ENETUNREACH : c_int = 51;
-            pub const ENETRESET : c_int = 52;
-            pub const ECONNABORTED : c_int = 53;
-            pub const ECONNRESET : c_int = 54;
-            pub const ENOBUFS : c_int = 55;
-            pub const EISCONN : c_int = 56;
-            pub const ENOTCONN : c_int = 57;
-            pub const ESHUTDOWN : c_int = 58;
-            pub const ETOOMANYREFS : c_int = 59;
-            pub const ETIMEDOUT : c_int = 60;
-            pub const ECONNREFUSED : c_int = 61;
-            pub const ELOOP : c_int = 62;
-            pub const ENAMETOOLONG : c_int = 63;
-            pub const EHOSTDOWN : c_int = 64;
-            pub const EHOSTUNREACH : c_int = 65;
-            pub const ENOTEMPTY : c_int = 66;
-            pub const EPROCLIM : c_int = 67;
-            pub const EUSERS : c_int = 68;
-            pub const EDQUOT : c_int = 69;
-            pub const ESTALE : c_int = 70;
-            pub const EREMOTE : c_int = 71;
-            pub const EBADRPC : c_int = 72;
-            pub const ERPCMISMATCH : c_int = 73;
-            pub const EPROGUNAVAIL : c_int = 74;
-            pub const EPROGMISMATCH : c_int = 75;
-            pub const EPROCUNAVAIL : c_int = 76;
-            pub const ENOLCK : c_int = 77;
-            pub const ENOSYS : c_int = 78;
-            pub const EFTYPE : c_int = 79;
-            pub const EAUTH : c_int = 80;
-            pub const ENEEDAUTH : c_int = 81;
-            pub const EIPSEC : c_int = 82;
-            pub const ENOATTR : c_int = 83;
-            pub const EILSEQ : c_int = 84;
-            pub const ENOMEDIUM : c_int = 85;
-            pub const EMEDIUMTYPE : c_int = 86;
-            pub const EOVERFLOW : c_int = 87;
-            pub const ECANCELED : c_int = 88;
-            pub const EIDRM : c_int = 89;
-            pub const ENOMSG : c_int = 90;
-            pub const ENOTSUP : c_int = 91;
-            pub const ELAST : c_int = 91; // must be equal to largest errno
+            pub const O_RDONLY: c_int = 0;
+            pub const O_WRONLY: c_int = 1;
+            pub const O_RDWR: c_int = 2;
+            pub const O_APPEND: c_int = 8;
+            pub const O_CREAT: c_int = 512;
+            pub const O_EXCL: c_int = 2048;
+            pub const O_NOCTTY: c_int = 32768;
+            pub const O_TRUNC: c_int = 1024;
+            pub const S_IFIFO: mode_t = 4096;
+            pub const S_IFCHR: mode_t = 8192;
+            pub const S_IFBLK: mode_t = 24576;
+            pub const S_IFDIR: mode_t = 16384;
+            pub const S_IFREG: mode_t = 32768;
+            pub const S_IFLNK: mode_t = 40960;
+            pub const S_IFSOCK: mode_t = 49152;
+            pub const S_IFMT: mode_t = 61440;
+            pub const S_IEXEC: mode_t = 64;
+            pub const S_IWRITE: mode_t = 128;
+            pub const S_IREAD: mode_t = 256;
+            pub const S_IRWXU: mode_t = 448;
+            pub const S_IXUSR: mode_t = 64;
+            pub const S_IWUSR: mode_t = 128;
+            pub const S_IRUSR: mode_t = 256;
+            pub const S_IRWXG: mode_t = 56;
+            pub const S_IXGRP: mode_t = 8;
+            pub const S_IWGRP: mode_t = 16;
+            pub const S_IRGRP: mode_t = 32;
+            pub const S_IRWXO: mode_t = 7;
+            pub const S_IXOTH: mode_t = 1;
+            pub const S_IWOTH: mode_t = 2;
+            pub const S_IROTH: mode_t = 4;
+            pub const F_OK: c_int = 0;
+            pub const R_OK: c_int = 4;
+            pub const W_OK: c_int = 2;
+            pub const X_OK: c_int = 1;
+            pub const STDIN_FILENO: c_int = 0;
+            pub const STDOUT_FILENO: c_int = 1;
+            pub const STDERR_FILENO: c_int = 2;
+            pub const F_LOCK: c_int = 1;
+            pub const F_TEST: c_int = 3;
+            pub const F_TLOCK: c_int = 2;
+            pub const F_ULOCK: c_int = 0;
+            pub const SIGHUP: c_int = 1;
+            pub const SIGINT: c_int = 2;
+            pub const SIGQUIT: c_int = 3;
+            pub const SIGILL: c_int = 4;
+            pub const SIGABRT: c_int = 6;
+            pub const SIGFPE: c_int = 8;
+            pub const SIGKILL: c_int = 9;
+            pub const SIGSEGV: c_int = 11;
+            pub const SIGPIPE: c_int = 13;
+            pub const SIGALRM: c_int = 14;
+            pub const SIGTERM: c_int = 15;
+
+            pub const PROT_NONE: c_int = 0;
+            pub const PROT_READ: c_int = 1;
+            pub const PROT_WRITE: c_int = 2;
+            pub const PROT_EXEC: c_int = 4;
+
+            pub const MAP_FILE: c_int = 0x0000;
+            pub const MAP_SHARED: c_int = 0x0001;
+            pub const MAP_PRIVATE: c_int = 0x0002;
+            pub const MAP_FIXED: c_int = 0x0010;
+            pub const MAP_ANON: c_int = 0x1000;
+
+            pub const MAP_FAILED: *mut c_void = !0 as *mut c_void;
+
+            pub const MCL_CURRENT: c_int = 0x0001;
+            pub const MCL_FUTURE: c_int = 0x0002;
+
+            pub const MS_ASYNC: c_int = 0x0001;
+            pub const MS_SYNC: c_int = 0x0002;
+            pub const MS_INVALIDATE: c_int = 0x0004;
+
+            pub const EPERM: c_int = 1;
+            pub const ENOENT: c_int = 2;
+            pub const ESRCH: c_int = 3;
+            pub const EINTR: c_int = 4;
+            pub const EIO: c_int = 5;
+            pub const ENXIO: c_int = 6;
+            pub const E2BIG: c_int = 7;
+            pub const ENOEXEC: c_int = 8;
+            pub const EBADF: c_int = 9;
+            pub const ECHILD: c_int = 10;
+            pub const EDEADLK: c_int = 11;
+            pub const ENOMEM: c_int = 12;
+            pub const EACCES: c_int = 13;
+            pub const EFAULT: c_int = 14;
+            pub const ENOTBLK: c_int = 15;
+            pub const EBUSY: c_int = 16;
+            pub const EEXIST: c_int = 17;
+            pub const EXDEV: c_int = 18;
+            pub const ENODEV: c_int = 19;
+            pub const ENOTDIR: c_int = 20;
+            pub const EISDIR: c_int = 21;
+            pub const EINVAL: c_int = 22;
+            pub const ENFILE: c_int = 23;
+            pub const EMFILE: c_int = 24;
+            pub const ENOTTY: c_int = 25;
+            pub const ETXTBSY: c_int = 26;
+            pub const EFBIG: c_int = 27;
+            pub const ENOSPC: c_int = 28;
+            pub const ESPIPE: c_int = 29;
+            pub const EROFS: c_int = 30;
+            pub const EMLINK: c_int = 31;
+            pub const EPIPE: c_int = 32;
+            pub const EDOM: c_int = 33;
+            pub const ERANGE: c_int = 34;
+            pub const EAGAIN: c_int = 35;
+            pub const EWOULDBLOCK: c_int = 35;
+            pub const EINPROGRESS: c_int = 36;
+            pub const EALREADY: c_int = 37;
+            pub const ENOTSOCK: c_int = 38;
+            pub const EDESTADDRREQ: c_int = 39;
+            pub const EMSGSIZE: c_int = 40;
+            pub const EPROTOTYPE: c_int = 41;
+            pub const ENOPROTOOPT: c_int = 42;
+            pub const EPROTONOSUPPORT: c_int = 43;
+            pub const ESOCKTNOSUPPORT: c_int = 44;
+            pub const EOPNOTSUPP: c_int = 45;
+            pub const EPFNOSUPPORT: c_int = 46;
+            pub const EAFNOSUPPORT: c_int = 47;
+            pub const EADDRINUSE: c_int = 48;
+            pub const EADDRNOTAVAIL: c_int = 49;
+            pub const ENETDOWN: c_int = 50;
+            pub const ENETUNREACH: c_int = 51;
+            pub const ENETRESET: c_int = 52;
+            pub const ECONNABORTED: c_int = 53;
+            pub const ECONNRESET: c_int = 54;
+            pub const ENOBUFS: c_int = 55;
+            pub const EISCONN: c_int = 56;
+            pub const ENOTCONN: c_int = 57;
+            pub const ESHUTDOWN: c_int = 58;
+            pub const ETOOMANYREFS: c_int = 59;
+            pub const ETIMEDOUT: c_int = 60;
+            pub const ECONNREFUSED: c_int = 61;
+            pub const ELOOP: c_int = 62;
+            pub const ENAMETOOLONG: c_int = 63;
+            pub const EHOSTDOWN: c_int = 64;
+            pub const EHOSTUNREACH: c_int = 65;
+            pub const ENOTEMPTY: c_int = 66;
+            pub const EPROCLIM: c_int = 67;
+            pub const EUSERS: c_int = 68;
+            pub const EDQUOT: c_int = 69;
+            pub const ESTALE: c_int = 70;
+            pub const EREMOTE: c_int = 71;
+            pub const EBADRPC: c_int = 72;
+            pub const ERPCMISMATCH: c_int = 73;
+            pub const EPROGUNAVAIL: c_int = 74;
+            pub const EPROGMISMATCH: c_int = 75;
+            pub const EPROCUNAVAIL: c_int = 76;
+            pub const ENOLCK: c_int = 77;
+            pub const ENOSYS: c_int = 78;
+            pub const EFTYPE: c_int = 79;
+            pub const EAUTH: c_int = 80;
+            pub const ENEEDAUTH: c_int = 81;
+            pub const EIPSEC: c_int = 82;
+            pub const ENOATTR: c_int = 83;
+            pub const EILSEQ: c_int = 84;
+            pub const ENOMEDIUM: c_int = 85;
+            pub const EMEDIUMTYPE: c_int = 86;
+            pub const EOVERFLOW: c_int = 87;
+            pub const ECANCELED: c_int = 88;
+            pub const EIDRM: c_int = 89;
+            pub const ENOMSG: c_int = 90;
+            pub const ENOTSUP: c_int = 91;
+            pub const ELAST: c_int = 91; // must be equal to largest errno
         }
         pub mod posix01 {
             use types::os::arch::c95::{c_int, size_t};
             use types::os::common::posix01::rlim_t;
 
-            pub const F_DUPFD : c_int = 0;
-            pub const F_GETFD : c_int = 1;
-            pub const F_SETFD : c_int = 2;
-            pub const F_GETFL : c_int = 3;
-            pub const F_SETFL : c_int = 4;
-            pub const F_GETOWN : c_int = 5;
-            pub const F_SETOWN : c_int = 6;
-            pub const F_GETLK : c_int = 7;
-            pub const F_SETLK : c_int = 8;
-            pub const F_SETLKW : c_int = 9;
-
-            pub const SIGTRAP : c_int = 5;
+            pub const F_DUPFD: c_int = 0;
+            pub const F_GETFD: c_int = 1;
+            pub const F_SETFD: c_int = 2;
+            pub const F_GETFL: c_int = 3;
+            pub const F_SETFL: c_int = 4;
+            pub const F_GETOWN: c_int = 5;
+            pub const F_SETOWN: c_int = 6;
+            pub const F_GETLK: c_int = 7;
+            pub const F_SETLK: c_int = 8;
+            pub const F_SETLKW: c_int = 9;
+
+            pub const SIGTRAP: c_int = 5;
             pub const SIG_IGN: size_t = 1;
 
-            pub const GLOB_APPEND   : c_int = 0x0001;
-            pub const GLOB_DOOFFS   : c_int = 0x0002;
-            pub const GLOB_ERR      : c_int = 0x0004;
-            pub const GLOB_MARK     : c_int = 0x0008;
-            pub const GLOB_NOCHECK  : c_int = 0x0010;
-            pub const GLOB_NOSORT   : c_int = 0x0020;
-            pub const GLOB_NOESCAPE : c_int = 0x1000;
-
-            pub const GLOB_NOSPACE  : c_int = -1;
-            pub const GLOB_ABORTED  : c_int = -2;
-            pub const GLOB_NOMATCH  : c_int = -3;
-            pub const GLOB_NOSYS : c_int = -4;
-
-            pub const POSIX_MADV_NORMAL : c_int = 0;
-            pub const POSIX_MADV_RANDOM : c_int = 1;
-            pub const POSIX_MADV_SEQUENTIAL : c_int = 2;
-            pub const POSIX_MADV_WILLNEED : c_int = 3;
-            pub const POSIX_MADV_DONTNEED : c_int = 4;
-
-            pub const _SC_IOV_MAX : c_int = 51;
-            pub const _SC_GETGR_R_SIZE_MAX : c_int = 100;
-            pub const _SC_GETPW_R_SIZE_MAX : c_int = 101;
-            pub const _SC_LOGIN_NAME_MAX : c_int = 102;
-            pub const _SC_MQ_PRIO_MAX : c_int = 59;
-            pub const _SC_THREAD_ATTR_STACKADDR : c_int = 77;
-            pub const _SC_THREAD_ATTR_STACKSIZE : c_int = 78;
-            pub const _SC_THREAD_DESTRUCTOR_ITERATIONS : c_int = 80;
-            pub const _SC_THREAD_KEYS_MAX : c_int = 81;
-            pub const _SC_THREAD_PRIO_INHERIT : c_int = 82;
-            pub const _SC_THREAD_PRIO_PROTECT : c_int = 83;
-            pub const _SC_THREAD_PRIORITY_SCHEDULING : c_int = 84;
-            pub const _SC_THREAD_PROCESS_SHARED : c_int = 85;
-            pub const _SC_THREAD_SAFE_FUNCTIONS : c_int = 103;
-            pub const _SC_THREAD_STACK_MIN : c_int = 89;
-            pub const _SC_THREAD_THREADS_MAX : c_int = 90;
-            pub const _SC_THREADS : c_int = 91;
-            pub const _SC_TTY_NAME_MAX : c_int = 107;
-            pub const _SC_ATEXIT_MAX : c_int = 46;
-            pub const _SC_XOPEN_CRYPT : c_int = 117;
-            pub const _SC_XOPEN_ENH_I18N : c_int = 118;
-            pub const _SC_XOPEN_LEGACY : c_int = 119;
-            pub const _SC_XOPEN_REALTIME : c_int = 120;
-            pub const _SC_XOPEN_REALTIME_THREADS : c_int = 121;
-            pub const _SC_XOPEN_SHM : c_int = 30;
-            pub const _SC_XOPEN_UNIX : c_int = 123;
-            pub const _SC_XOPEN_VERSION : c_int = 125;
-
-            pub const PTHREAD_CREATE_JOINABLE : c_int = 0;
-            pub const PTHREAD_CREATE_DETACHED : c_int = 1;
-            pub const PTHREAD_STACK_MIN : size_t = 2048;
-
-            pub const CLOCK_REALTIME : c_int = 0;
-            pub const CLOCK_MONOTONIC : c_int = 3;
+            pub const GLOB_APPEND: c_int = 0x0001;
+            pub const GLOB_DOOFFS: c_int = 0x0002;
+            pub const GLOB_ERR: c_int = 0x0004;
+            pub const GLOB_MARK: c_int = 0x0008;
+            pub const GLOB_NOCHECK: c_int = 0x0010;
+            pub const GLOB_NOSORT: c_int = 0x0020;
+            pub const GLOB_NOESCAPE: c_int = 0x1000;
+
+            pub const GLOB_NOSPACE: c_int = -1;
+            pub const GLOB_ABORTED: c_int = -2;
+            pub const GLOB_NOMATCH: c_int = -3;
+            pub const GLOB_NOSYS: c_int = -4;
+
+            pub const POSIX_MADV_NORMAL: c_int = 0;
+            pub const POSIX_MADV_RANDOM: c_int = 1;
+            pub const POSIX_MADV_SEQUENTIAL: c_int = 2;
+            pub const POSIX_MADV_WILLNEED: c_int = 3;
+            pub const POSIX_MADV_DONTNEED: c_int = 4;
+
+            pub const _SC_IOV_MAX: c_int = 51;
+            pub const _SC_GETGR_R_SIZE_MAX: c_int = 100;
+            pub const _SC_GETPW_R_SIZE_MAX: c_int = 101;
+            pub const _SC_LOGIN_NAME_MAX: c_int = 102;
+            pub const _SC_MQ_PRIO_MAX: c_int = 59;
+            pub const _SC_THREAD_ATTR_STACKADDR: c_int = 77;
+            pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 78;
+            pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 80;
+            pub const _SC_THREAD_KEYS_MAX: c_int = 81;
+            pub const _SC_THREAD_PRIO_INHERIT: c_int = 82;
+            pub const _SC_THREAD_PRIO_PROTECT: c_int = 83;
+            pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 84;
+            pub const _SC_THREAD_PROCESS_SHARED: c_int = 85;
+            pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 103;
+            pub const _SC_THREAD_STACK_MIN: c_int = 89;
+            pub const _SC_THREAD_THREADS_MAX: c_int = 90;
+            pub const _SC_THREADS: c_int = 91;
+            pub const _SC_TTY_NAME_MAX: c_int = 107;
+            pub const _SC_ATEXIT_MAX: c_int = 46;
+            pub const _SC_XOPEN_CRYPT: c_int = 117;
+            pub const _SC_XOPEN_ENH_I18N: c_int = 118;
+            pub const _SC_XOPEN_LEGACY: c_int = 119;
+            pub const _SC_XOPEN_REALTIME: c_int = 120;
+            pub const _SC_XOPEN_REALTIME_THREADS: c_int = 121;
+            pub const _SC_XOPEN_SHM: c_int = 30;
+            pub const _SC_XOPEN_UNIX: c_int = 123;
+            pub const _SC_XOPEN_VERSION: c_int = 125;
+
+            pub const PTHREAD_CREATE_JOINABLE: c_int = 0;
+            pub const PTHREAD_CREATE_DETACHED: c_int = 1;
+            pub const PTHREAD_STACK_MIN: size_t = 2048;
+
+            pub const CLOCK_REALTIME: c_int = 0;
+            pub const CLOCK_MONOTONIC: c_int = 3;
 
             pub const RLIMIT_CPU: c_int = 0;
             pub const RLIMIT_FSIZE: c_int = 1;
@@ -4737,27 +4995,20 @@ pub mod consts {
             pub const RUSAGE_CHILDREN: c_int = -1;
             pub const RUSAGE_THREAD: c_int = 1;
         }
-        #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
         pub mod posix08 {
             use types::os::arch::c95::c_int;
             pub const O_CLOEXEC: c_int = 0x10000;
             pub const F_DUPFD_CLOEXEC: c_int = 10;
         }
-        #[cfg(target_os = "netbsd")]
-        pub mod posix08 {
-            use types::os::arch::c95::c_int;
-            pub const O_CLOEXEC: c_int = 0x400000;
-            pub const F_DUPFD_CLOEXEC: c_int = 12;
-        }
         pub mod bsd44 {
             use types::os::arch::c95::c_int;
 
-            pub const MADV_NORMAL : c_int = 0;
-            pub const MADV_RANDOM : c_int = 1;
-            pub const MADV_SEQUENTIAL : c_int = 2;
-            pub const MADV_WILLNEED : c_int = 3;
-            pub const MADV_DONTNEED : c_int = 4;
-            pub const MADV_FREE : c_int = 6;
+            pub const MADV_NORMAL: c_int = 0;
+            pub const MADV_RANDOM: c_int = 1;
+            pub const MADV_SEQUENTIAL: c_int = 2;
+            pub const MADV_WILLNEED: c_int = 3;
+            pub const MADV_DONTNEED: c_int = 4;
+            pub const MADV_FREE: c_int = 6;
 
             pub const AF_UNIX: c_int = 1;
             pub const AF_INET: c_int = 2;
@@ -4812,77 +5063,481 @@ pub mod consts {
         pub mod extra {
             use types::os::arch::c95::c_int;
 
-            pub const O_DSYNC : c_int = 128; // same as SYNC
-            pub const O_SYNC : c_int = 128;
-            pub const O_NONBLOCK : c_int = 4;
-            pub const CTL_KERN : c_int = 1;
-            pub const KERN_PROC : c_int = 66;
+            pub const O_DSYNC: c_int = 128; // same as SYNC
+            pub const O_SYNC: c_int = 128;
+            pub const O_NONBLOCK: c_int = 4;
+            pub const CTL_KERN: c_int = 1;
+            pub const KERN_PROC: c_int = 66;
 
-            pub const MAP_COPY : c_int = 0x0002;
-            pub const MAP_RENAME : c_int = 0x0000;
-            pub const MAP_NORESERVE : c_int = 0x0000;
-            pub const MAP_NOEXTEND : c_int = 0x0000;
-            pub const MAP_HASSEMAPHORE : c_int = 0x0000;
+            pub const MAP_COPY: c_int = 0x0002;
+            pub const MAP_RENAME: c_int = 0x0000;
+            pub const MAP_NORESERVE: c_int = 0x0000;
+            pub const MAP_NOEXTEND: c_int = 0x0000;
+            pub const MAP_HASSEMAPHORE: c_int = 0x0000;
 
-            pub const IPPROTO_RAW : c_int = 255;
+            pub const IPPROTO_RAW: c_int = 255;
 
             pub const PATH_MAX: c_int = 1024;
         }
         pub mod sysconf {
             use types::os::arch::c95::c_int;
 
-            pub const _SC_ARG_MAX : c_int = 1;
-            pub const _SC_CHILD_MAX : c_int = 2;
-            pub const _SC_CLK_TCK : c_int = 3;
-            pub const _SC_NGROUPS_MAX : c_int = 4;
-            pub const _SC_OPEN_MAX : c_int = 5;
-            pub const _SC_JOB_CONTROL : c_int = 6;
-            pub const _SC_SAVED_IDS : c_int = 7;
-            pub const _SC_VERSION : c_int = 8;
-            pub const _SC_BC_BASE_MAX : c_int = 9;
-            pub const _SC_BC_DIM_MAX : c_int = 10;
-            pub const _SC_BC_SCALE_MAX : c_int = 11;
-            pub const _SC_BC_STRING_MAX : c_int = 12;
-            pub const _SC_COLL_WEIGHTS_MAX : c_int = 13;
-            pub const _SC_EXPR_NEST_MAX : c_int = 14;
-            pub const _SC_LINE_MAX : c_int = 15;
-            pub const _SC_RE_DUP_MAX : c_int = 16;
-            pub const _SC_2_VERSION : c_int = 17;
-            pub const _SC_2_C_BIND : c_int = 18;
-            pub const _SC_2_C_DEV : c_int = 19;
-            pub const _SC_2_CHAR_TERM : c_int = 20;
-            pub const _SC_2_FORT_DEV : c_int = 21;
-            pub const _SC_2_FORT_RUN : c_int = 22;
-            pub const _SC_2_LOCALEDEF : c_int = 23;
-            pub const _SC_2_SW_DEV : c_int = 24;
-            pub const _SC_2_UPE : c_int = 25;
-            pub const _SC_STREAM_MAX : c_int = 26;
-            pub const _SC_TZNAME_MAX : c_int = 27;
-            pub const _SC_PAGESIZE : c_int = 28;
-            pub const _SC_FSYNC : c_int = 29;
-            pub const _SC_SEM_NSEMS_MAX : c_int = 31;
-            pub const _SC_SEM_VALUE_MAX : c_int = 32;
-            pub const _SC_AIO_LISTIO_MAX : c_int = 42;
-            pub const _SC_AIO_MAX : c_int = 43;
-            pub const _SC_AIO_PRIO_DELTA_MAX : c_int = 44;
-            pub const _SC_ASYNCHRONOUS_IO : c_int = 45;
-            pub const _SC_DELAYTIMER_MAX : c_int = 50;
-            pub const _SC_MAPPED_FILES : c_int = 53;
-            pub const _SC_MEMLOCK : c_int = 54;
-            pub const _SC_MEMLOCK_RANGE : c_int = 55;
-            pub const _SC_MEMORY_PROTECTION : c_int = 56;
-            pub const _SC_MESSAGE_PASSING : c_int = 57;
-            pub const _SC_MQ_OPEN_MAX : c_int = 58;
-            pub const _SC_PRIORITIZED_IO : c_int = 60;
-            pub const _SC_PRIORITY_SCHEDULING : c_int = 61;
-            pub const _SC_REALTIME_SIGNALS : c_int = 64;
-            pub const _SC_RTSIG_MAX : c_int = 66;
-            pub const _SC_SEMAPHORES : c_int = 67;
-            pub const _SC_SHARED_MEMORY_OBJECTS : c_int = 68;
-            pub const _SC_SIGQUEUE_MAX : c_int = 70;
-            pub const _SC_SYNCHRONIZED_IO : c_int = 75;
-            pub const _SC_TIMER_MAX : c_int = 93;
-            pub const _SC_TIMERS : c_int = 94;
+            pub const _SC_ARG_MAX: c_int = 1;
+            pub const _SC_CHILD_MAX: c_int = 2;
+            pub const _SC_CLK_TCK: c_int = 3;
+            pub const _SC_NGROUPS_MAX: c_int = 4;
+            pub const _SC_OPEN_MAX: c_int = 5;
+            pub const _SC_JOB_CONTROL: c_int = 6;
+            pub const _SC_SAVED_IDS: c_int = 7;
+            pub const _SC_VERSION: c_int = 8;
+            pub const _SC_BC_BASE_MAX: c_int = 9;
+            pub const _SC_BC_DIM_MAX: c_int = 10;
+            pub const _SC_BC_SCALE_MAX: c_int = 11;
+            pub const _SC_BC_STRING_MAX: c_int = 12;
+            pub const _SC_COLL_WEIGHTS_MAX: c_int = 13;
+            pub const _SC_EXPR_NEST_MAX: c_int = 14;
+            pub const _SC_LINE_MAX: c_int = 15;
+            pub const _SC_RE_DUP_MAX: c_int = 16;
+            pub const _SC_2_VERSION: c_int = 17;
+            pub const _SC_2_C_BIND: c_int = 18;
+            pub const _SC_2_C_DEV: c_int = 19;
+            pub const _SC_2_CHAR_TERM: c_int = 20;
+            pub const _SC_2_FORT_DEV: c_int = 21;
+            pub const _SC_2_FORT_RUN: c_int = 22;
+            pub const _SC_2_LOCALEDEF: c_int = 23;
+            pub const _SC_2_SW_DEV: c_int = 24;
+            pub const _SC_2_UPE: c_int = 25;
+            pub const _SC_STREAM_MAX: c_int = 26;
+            pub const _SC_TZNAME_MAX: c_int = 27;
+            pub const _SC_PAGESIZE: c_int = 28;
+            pub const _SC_FSYNC: c_int = 29;
+            pub const _SC_SEM_NSEMS_MAX: c_int = 31;
+            pub const _SC_SEM_VALUE_MAX: c_int = 32;
+            pub const _SC_AIO_LISTIO_MAX: c_int = 42;
+            pub const _SC_AIO_MAX: c_int = 43;
+            pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 44;
+            pub const _SC_ASYNCHRONOUS_IO: c_int = 45;
+            pub const _SC_DELAYTIMER_MAX: c_int = 50;
+            pub const _SC_MAPPED_FILES: c_int = 53;
+            pub const _SC_MEMLOCK: c_int = 54;
+            pub const _SC_MEMLOCK_RANGE: c_int = 55;
+            pub const _SC_MEMORY_PROTECTION: c_int = 56;
+            pub const _SC_MESSAGE_PASSING: c_int = 57;
+            pub const _SC_MQ_OPEN_MAX: c_int = 58;
+            pub const _SC_PRIORITIZED_IO: c_int = 60;
+            pub const _SC_PRIORITY_SCHEDULING: c_int = 61;
+            pub const _SC_REALTIME_SIGNALS: c_int = 64;
+            pub const _SC_RTSIG_MAX: c_int = 66;
+            pub const _SC_SEMAPHORES: c_int = 67;
+            pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 68;
+            pub const _SC_SIGQUEUE_MAX: c_int = 70;
+            pub const _SC_SYNCHRONIZED_IO: c_int = 75;
+            pub const _SC_TIMER_MAX: c_int = 93;
+            pub const _SC_TIMERS: c_int = 94;
+
+            pub const _PC_NAME_MAX: c_int = 4;
+            pub const _PC_PATH_MAX: c_int = 5;
+        }
+    }
+
+    #[cfg(target_os = "netbsd")]
+    pub mod os {
+        pub mod c95 {
+            use types::os::arch::c95::{c_int, c_uint};
+
+            pub const EXIT_FAILURE: c_int = 1;
+            pub const EXIT_SUCCESS: c_int = 0;
+            pub const RAND_MAX: c_int = 2147483647;
+            pub const EOF: c_int = -1;
+            pub const SEEK_SET: c_int = 0;
+            pub const SEEK_CUR: c_int = 1;
+            pub const SEEK_END: c_int = 2;
+            pub const _IOFBF: c_int = 0;
+            pub const _IONBF: c_int = 2;
+            pub const _IOLBF: c_int = 1;
+            pub const BUFSIZ: c_uint = 1024;
+            pub const FOPEN_MAX: c_uint = 20;
+            pub const FILENAME_MAX: c_uint = 1024;
+            pub const L_tmpnam: c_uint = 1024;
+            pub const TMP_MAX: c_uint = 308915776;
+        }
+        pub mod c99 {
+        }
+        pub mod posix88 {
+            use types::common::c95::c_void;
+            use types::os::arch::c95::c_int;
+            use types::os::arch::posix88::mode_t;
+
+            pub const O_RDONLY: c_int = 0;
+            pub const O_WRONLY: c_int = 1;
+            pub const O_RDWR: c_int = 2;
+            pub const O_APPEND: c_int = 8;
+            pub const O_CREAT: c_int = 512;
+            pub const O_EXCL: c_int = 2048;
+            pub const O_NOCTTY: c_int = 32768;
+            pub const O_TRUNC: c_int = 1024;
+            pub const S_IFIFO: mode_t = 4096;
+            pub const S_IFCHR: mode_t = 8192;
+            pub const S_IFBLK: mode_t = 24576;
+            pub const S_IFDIR: mode_t = 16384;
+            pub const S_IFREG: mode_t = 32768;
+            pub const S_IFLNK: mode_t = 40960;
+            pub const S_IFSOCK: mode_t = 49152;
+            pub const S_IFMT: mode_t = 61440;
+            pub const S_IEXEC: mode_t = 64;
+            pub const S_IWRITE: mode_t = 128;
+            pub const S_IREAD: mode_t = 256;
+            pub const S_IRWXU: mode_t = 448;
+            pub const S_IXUSR: mode_t = 64;
+            pub const S_IWUSR: mode_t = 128;
+            pub const S_IRUSR: mode_t = 256;
+            pub const S_IRWXG: mode_t = 56;
+            pub const S_IXGRP: mode_t = 8;
+            pub const S_IWGRP: mode_t = 16;
+            pub const S_IRGRP: mode_t = 32;
+            pub const S_IRWXO: mode_t = 7;
+            pub const S_IXOTH: mode_t = 1;
+            pub const S_IWOTH: mode_t = 2;
+            pub const S_IROTH: mode_t = 4;
+            pub const F_OK: c_int = 0;
+            pub const R_OK: c_int = 4;
+            pub const W_OK: c_int = 2;
+            pub const X_OK: c_int = 1;
+            pub const STDIN_FILENO: c_int = 0;
+            pub const STDOUT_FILENO: c_int = 1;
+            pub const STDERR_FILENO: c_int = 2;
+            pub const F_LOCK: c_int = 1;
+            pub const F_TEST: c_int = 3;
+            pub const F_TLOCK: c_int = 2;
+            pub const F_ULOCK: c_int = 0;
+            pub const SIGHUP: c_int = 1;
+            pub const SIGINT: c_int = 2;
+            pub const SIGQUIT: c_int = 3;
+            pub const SIGILL: c_int = 4;
+            pub const SIGABRT: c_int = 6;
+            pub const SIGFPE: c_int = 8;
+            pub const SIGKILL: c_int = 9;
+            pub const SIGSEGV: c_int = 11;
+            pub const SIGPIPE: c_int = 13;
+            pub const SIGALRM: c_int = 14;
+            pub const SIGTERM: c_int = 15;
+
+            pub const PROT_NONE: c_int = 0;
+            pub const PROT_READ: c_int = 1;
+            pub const PROT_WRITE: c_int = 2;
+            pub const PROT_EXEC: c_int = 4;
+
+            pub const MAP_FILE: c_int = 0;
+            pub const MAP_SHARED: c_int = 1;
+            pub const MAP_PRIVATE: c_int = 2;
+            pub const MAP_FIXED: c_int = 16;
+            pub const MAP_ANON: c_int = 4096;
+
+            pub const MAP_FAILED: *mut c_void = !0 as *mut c_void;
+
+            pub const MCL_CURRENT: c_int = 1;
+            pub const MCL_FUTURE: c_int = 2;
+
+            pub const MS_ASYNC: c_int = 1;
+            pub const MS_SYNC: c_int = 4;
+            pub const MS_INVALIDATE: c_int = 2;
+
+            pub const EPERM: c_int = 1;
+            pub const ENOENT: c_int = 2;
+            pub const ESRCH: c_int = 3;
+            pub const EINTR: c_int = 4;
+            pub const EIO: c_int = 5;
+            pub const ENXIO: c_int = 6;
+            pub const E2BIG: c_int = 7;
+            pub const ENOEXEC: c_int = 8;
+            pub const EBADF: c_int = 9;
+            pub const ECHILD: c_int = 10;
+            pub const EDEADLK: c_int = 11;
+            pub const ENOMEM: c_int = 12;
+            pub const EACCES: c_int = 13;
+            pub const EFAULT: c_int = 14;
+            pub const ENOTBLK: c_int = 15;
+            pub const EBUSY: c_int = 16;
+            pub const EEXIST: c_int = 17;
+            pub const EXDEV: c_int = 18;
+            pub const ENODEV: c_int = 19;
+            pub const ENOTDIR: c_int = 20;
+            pub const EISDIR: c_int = 21;
+            pub const EINVAL: c_int = 22;
+            pub const ENFILE: c_int = 23;
+            pub const EMFILE: c_int = 24;
+            pub const ENOTTY: c_int = 25;
+            pub const ETXTBSY: c_int = 26;
+            pub const EFBIG: c_int = 27;
+            pub const ENOSPC: c_int = 28;
+            pub const ESPIPE: c_int = 29;
+            pub const EROFS: c_int = 30;
+            pub const EMLINK: c_int = 31;
+            pub const EPIPE: c_int = 32;
+            pub const EDOM: c_int = 33;
+            pub const ERANGE: c_int = 34;
+            pub const EAGAIN: c_int = 35;
+            pub const EWOULDBLOCK: c_int = 35;
+            pub const EINPROGRESS: c_int = 36;
+            pub const EALREADY: c_int = 37;
+            pub const ENOTSOCK: c_int = 38;
+            pub const EDESTADDRREQ: c_int = 39;
+            pub const EMSGSIZE: c_int = 40;
+            pub const EPROTOTYPE: c_int = 41;
+            pub const ENOPROTOOPT: c_int = 42;
+            pub const EPROTONOSUPPORT: c_int = 43;
+            pub const ESOCKTNOSUPPORT: c_int = 44;
+            pub const EOPNOTSUPP: c_int = 45;
+            pub const EPFNOSUPPORT: c_int = 46;
+            pub const EAFNOSUPPORT: c_int = 47;
+            pub const EADDRINUSE: c_int = 48;
+            pub const EADDRNOTAVAIL: c_int = 49;
+            pub const ENETDOWN: c_int = 50;
+            pub const ENETUNREACH: c_int = 51;
+            pub const ENETRESET: c_int = 52;
+            pub const ECONNABORTED: c_int = 53;
+            pub const ECONNRESET: c_int = 54;
+            pub const ENOBUFS: c_int = 55;
+            pub const EISCONN: c_int = 56;
+            pub const ENOTCONN: c_int = 57;
+            pub const ESHUTDOWN: c_int = 58;
+            pub const ETOOMANYREFS: c_int = 59;
+            pub const ETIMEDOUT: c_int = 60;
+            pub const ECONNREFUSED: c_int = 61;
+            pub const ELOOP: c_int = 62;
+            pub const ENAMETOOLONG: c_int = 63;
+            pub const EHOSTDOWN: c_int = 64;
+            pub const EHOSTUNREACH: c_int = 65;
+            pub const ENOTEMPTY: c_int = 66;
+            pub const EPROCLIM: c_int = 67;
+            pub const EUSERS: c_int = 68;
+            pub const EDQUOT: c_int = 69;
+            pub const ESTALE: c_int = 70;
+            pub const EREMOTE: c_int = 71;
+            pub const EBADRPC: c_int = 72;
+            pub const ERPCMISMATCH: c_int = 73;
+            pub const EPROGUNAVAIL: c_int = 74;
+            pub const EPROGMISMATCH: c_int = 75;
+            pub const EPROCUNAVAIL: c_int = 76;
+            pub const ENOLCK: c_int = 77;
+            pub const ENOSYS: c_int = 78;
+            pub const EFTYPE: c_int = 79;
+            pub const EAUTH: c_int = 80;
+            pub const ENEEDAUTH: c_int = 81;
+            pub const ENOATTR: c_int = 93;
+            pub const EILSEQ: c_int = 85;
+            pub const EOVERFLOW: c_int = 84;
+            pub const ECANCELED: c_int = 87;
+            pub const EIDRM: c_int = 82;
+            pub const ENOMSG: c_int = 83;
+            pub const ENOTSUP: c_int = 86;
+            pub const ELAST: c_int = 96;
+        }
+        pub mod posix01 {
+            use types::os::arch::c95::{c_int, size_t};
+            use types::os::common::posix01::rlim_t;
+
+            pub const F_DUPFD: c_int = 0;
+            pub const F_GETFD: c_int = 1;
+            pub const F_SETFD: c_int = 2;
+            pub const F_GETFL: c_int = 3;
+            pub const F_SETFL: c_int = 4;
+            pub const F_GETOWN: c_int = 5;
+            pub const F_SETOWN: c_int = 6;
+            pub const F_GETLK: c_int = 7;
+            pub const F_SETLK: c_int = 8;
+            pub const F_SETLKW: c_int = 9;
+
+            pub const SIGTRAP: c_int = 5;
+            pub const SIG_IGN: size_t = 1;
+
+            pub const GLOB_APPEND: c_int = 1;
+            pub const GLOB_DOOFFS: c_int = 2;
+            pub const GLOB_ERR: c_int = 4;
+            pub const GLOB_MARK: c_int = 8;
+            pub const GLOB_NOCHECK: c_int = 16;
+            pub const GLOB_NOSORT: c_int = 32;
+            pub const GLOB_NOESCAPE: c_int = 4096;
+
+            pub const GLOB_NOSPACE: c_int = -1;
+            pub const GLOB_ABORTED: c_int = -2;
+            pub const GLOB_NOMATCH: c_int = -3;
+            pub const GLOB_NOSYS: c_int = -4;
+
+            pub const POSIX_MADV_NORMAL: c_int = 0;
+            pub const POSIX_MADV_RANDOM: c_int = 1;
+            pub const POSIX_MADV_SEQUENTIAL: c_int = 2;
+            pub const POSIX_MADV_WILLNEED: c_int = 3;
+            pub const POSIX_MADV_DONTNEED: c_int = 4;
+
+            pub const _SC_IOV_MAX: c_int = 32;
+            pub const _SC_GETGR_R_SIZE_MAX: c_int = 47;
+            pub const _SC_GETPW_R_SIZE_MAX: c_int = 48;
+            pub const _SC_LOGIN_NAME_MAX: c_int = 37;
+            pub const _SC_MQ_PRIO_MAX: c_int = 55;
+            pub const _SC_THREAD_ATTR_STACKADDR: c_int = 61;
+            pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 62;
+            pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 57;
+            pub const _SC_THREAD_KEYS_MAX: c_int = 58;
+            pub const _SC_THREAD_PRIO_INHERIT: c_int = 64;
+            pub const _SC_THREAD_PRIO_PROTECT: c_int = 65;
+            pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 63;
+            pub const _SC_THREAD_PROCESS_SHARED: c_int = 66;
+            pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 67;
+            pub const _SC_THREAD_STACK_MIN: c_int = 59;
+            pub const _SC_THREAD_THREADS_MAX: c_int = 60;
+            pub const _SC_THREADS: c_int = 41;
+            pub const _SC_TTY_NAME_MAX: c_int = 68;
+            pub const _SC_ATEXIT_MAX: c_int = 40;
+            pub const _SC_XOPEN_SHM: c_int = 30;
+
+            pub const PTHREAD_CREATE_JOINABLE: c_int = 0;
+            pub const PTHREAD_CREATE_DETACHED: c_int = 1;
+            pub const PTHREAD_STACK_MIN: size_t = 2048;
+
+            pub const CLOCK_REALTIME: c_int = 0;
+            pub const CLOCK_MONOTONIC: c_int = 3;
+
+            pub const RLIMIT_CPU: c_int = 0;
+            pub const RLIMIT_FSIZE: c_int = 1;
+            pub const RLIMIT_DATA: c_int = 2;
+            pub const RLIMIT_STACK: c_int = 3;
+            pub const RLIMIT_CORE: c_int = 4;
+            pub const RLIMIT_RSS: c_int = 5;
+            pub const RLIMIT_MEMLOCK: c_int = 6;
+            pub const RLIMIT_NPROC: c_int = 7;
+            pub const RLIMIT_NOFILE: c_int = 8;
+            pub const RLIM_NLIMITS: c_int = 9;
+
+            pub const RLIM_INFINITY: rlim_t = 0x7fff_ffff_ffff_ffff;
+            pub const RLIM_SAVED_MAX: rlim_t = RLIM_INFINITY;
+            pub const RLIM_SAVED_CUR: rlim_t = RLIM_INFINITY;
+
+            pub const RUSAGE_SELF: c_int = 0;
+            pub const RUSAGE_CHILDREN: c_int = -1;
+            pub const RUSAGE_THREAD: c_int = 1;
+        }
+        pub mod posix08 {
+            use types::os::arch::c95::c_int;
+            pub const O_CLOEXEC: c_int = 0x400000;
+            pub const F_DUPFD_CLOEXEC: c_int = 12;
+        }
+        pub mod bsd44 {
+            use types::os::arch::c95::c_int;
+
+            pub const MADV_NORMAL: c_int = 0;
+            pub const MADV_RANDOM: c_int = 1;
+            pub const MADV_SEQUENTIAL: c_int = 2;
+            pub const MADV_WILLNEED: c_int = 3;
+            pub const MADV_DONTNEED: c_int = 4;
+            pub const MADV_FREE: c_int = 6;
+
+            pub const AF_UNIX: c_int = 1;
+            pub const AF_INET: c_int = 2;
+            pub const AF_INET6: c_int = 24;
+            pub const SOCK_STREAM: c_int = 1;
+            pub const SOCK_DGRAM: c_int = 2;
+            pub const SOCK_RAW: c_int = 3;
+            pub const IPPROTO_TCP: c_int = 6;
+            pub const IPPROTO_IP: c_int = 0;
+            pub const IPPROTO_IPV6: c_int = 41;
+            pub const IP_MULTICAST_TTL: c_int = 10;
+            pub const IP_MULTICAST_LOOP: c_int = 11;
+            pub const IP_TTL: c_int = 4;
+            pub const IP_HDRINCL: c_int = 2;
+            pub const IP_ADD_MEMBERSHIP: c_int = 12;
+            pub const IP_DROP_MEMBERSHIP: c_int = 13;
+
+            pub const TCP_NODELAY: c_int = 1;
+            pub const SOL_SOCKET: c_int = 65535;
+            pub const SO_DEBUG: c_int = 1;
+            pub const SO_ACCEPTCONN: c_int = 2;
+            pub const SO_REUSEADDR: c_int = 4;
+            pub const SO_KEEPALIVE: c_int = 8;
+            pub const SO_DONTROUTE: c_int = 16;
+            pub const SO_BROADCAST: c_int = 32;
+            pub const SO_USELOOPBACK: c_int = 64;
+            pub const SO_LINGER: c_int = 128;
+            pub const SO_OOBINLINE: c_int = 256;
+            pub const SO_REUSEPORT: c_int = 512;
+            pub const SO_SNDBUF: c_int = 4097;
+            pub const SO_RCVBUF: c_int = 4098;
+            pub const SO_SNDLOWAT: c_int = 4099;
+            pub const SO_RCVLOWAT: c_int = 4100;
+            pub const SO_SNDTIMEO: c_int = 4107;
+            pub const SO_RCVTIMEO: c_int = 4108;
+            pub const SO_ERROR: c_int = 4103;
+            pub const SO_TYPE: c_int = 4104;
+
+            pub const IFF_LOOPBACK: c_int = 0x8;
+
+            pub const SHUT_RD: c_int = 0;
+            pub const SHUT_WR: c_int = 1;
+            pub const SHUT_RDWR: c_int = 2;
+
+            pub const LOCK_SH: c_int = 1;
+            pub const LOCK_EX: c_int = 2;
+            pub const LOCK_NB: c_int = 4;
+            pub const LOCK_UN: c_int = 8;
+        }
+        pub mod extra {
+            use types::os::arch::c95::c_int;
+
+
+            pub const MAP_RENAME: c_int = 32;
+            pub const MAP_NORESERVE: c_int = 64;
+            pub const MAP_HASSEMAPHORE: c_int = 512;
+
+            pub const IPPROTO_RAW: c_int = 255;
+
+            pub const PATH_MAX: c_int = 1024;
+        }
+        pub mod sysconf {
+            use types::os::arch::c95::c_int;
+
+            pub const _SC_ARG_MAX: c_int = 1;
+            pub const _SC_CHILD_MAX: c_int = 2;
+            pub const _SC_CLK_TCK: c_int = 39;
+            pub const _SC_NGROUPS_MAX: c_int = 4;
+            pub const _SC_OPEN_MAX: c_int = 5;
+            pub const _SC_JOB_CONTROL: c_int = 6;
+            pub const _SC_SAVED_IDS: c_int = 7;
+            pub const _SC_VERSION: c_int = 8;
+            pub const _SC_BC_BASE_MAX: c_int = 9;
+            pub const _SC_BC_DIM_MAX: c_int = 10;
+            pub const _SC_BC_SCALE_MAX: c_int = 11;
+            pub const _SC_BC_STRING_MAX: c_int = 12;
+            pub const _SC_COLL_WEIGHTS_MAX: c_int = 13;
+            pub const _SC_EXPR_NEST_MAX: c_int = 14;
+            pub const _SC_LINE_MAX: c_int = 15;
+            pub const _SC_RE_DUP_MAX: c_int = 16;
+            pub const _SC_2_VERSION: c_int = 17;
+            pub const _SC_2_C_BIND: c_int = 18;
+            pub const _SC_2_C_DEV: c_int = 19;
+            pub const _SC_2_CHAR_TERM: c_int = 20;
+            pub const _SC_2_FORT_DEV: c_int = 21;
+            pub const _SC_2_FORT_RUN: c_int = 22;
+            pub const _SC_2_LOCALEDEF: c_int = 23;
+            pub const _SC_2_SW_DEV: c_int = 24;
+            pub const _SC_2_UPE: c_int = 25;
+            pub const _SC_STREAM_MAX: c_int = 26;
+            pub const _SC_TZNAME_MAX: c_int = 27;
+            pub const _SC_PAGESIZE: c_int = 28;
+            pub const _SC_FSYNC: c_int = 29;
+            pub const _SC_AIO_LISTIO_MAX: c_int = 51;
+            pub const _SC_AIO_MAX: c_int = 52;
+            pub const _SC_ASYNCHRONOUS_IO: c_int = 50;
+            pub const _SC_MAPPED_FILES: c_int = 33;
+            pub const _SC_MEMLOCK: c_int = 34;
+            pub const _SC_MEMLOCK_RANGE: c_int = 35;
+            pub const _SC_MEMORY_PROTECTION: c_int = 36;
+            pub const _SC_MESSAGE_PASSING: c_int = 53;
+            pub const _SC_MQ_OPEN_MAX: c_int = 54;
+            pub const _SC_PRIORITY_SCHEDULING: c_int = 56;
+            pub const _SC_SEMAPHORES: c_int = 42;
+            pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 87;
+            pub const _SC_SYNCHRONIZED_IO: c_int = 31;
+            pub const _SC_TIMERS: c_int = 44;
 
             pub const _PC_NAME_MAX: c_int = 4;
             pub const _PC_PATH_MAX: c_int = 5;
@@ -4894,21 +5549,21 @@ pub mod consts {
         pub mod c95 {
             use types::os::arch::c95::{c_int, c_uint};
 
-            pub const EXIT_FAILURE : c_int = 1;
-            pub const EXIT_SUCCESS : c_int = 0;
-            pub const RAND_MAX : c_int = 2147483647;
-            pub const EOF : c_int = -1;
-            pub const SEEK_SET : c_int = 0;
-            pub const SEEK_CUR : c_int = 1;
-            pub const SEEK_END : c_int = 2;
-            pub const _IOFBF : c_int = 0;
-            pub const _IONBF : c_int = 2;
-            pub const _IOLBF : c_int = 1;
-            pub const BUFSIZ : c_uint = 1024;
-            pub const FOPEN_MAX : c_uint = 20;
-            pub const FILENAME_MAX : c_uint = 1024;
-            pub const L_tmpnam : c_uint = 1024;
-            pub const TMP_MAX : c_uint = 308915776;
+            pub const EXIT_FAILURE: c_int = 1;
+            pub const EXIT_SUCCESS: c_int = 0;
+            pub const RAND_MAX: c_int = 2147483647;
+            pub const EOF: c_int = -1;
+            pub const SEEK_SET: c_int = 0;
+            pub const SEEK_CUR: c_int = 1;
+            pub const SEEK_END: c_int = 2;
+            pub const _IOFBF: c_int = 0;
+            pub const _IONBF: c_int = 2;
+            pub const _IOLBF: c_int = 1;
+            pub const BUFSIZ: c_uint = 1024;
+            pub const FOPEN_MAX: c_uint = 20;
+            pub const FILENAME_MAX: c_uint = 1024;
+            pub const L_tmpnam: c_uint = 1024;
+            pub const TMP_MAX: c_uint = 308915776;
         }
         pub mod c99 {
         }
@@ -4917,253 +5572,253 @@ pub mod consts {
             use types::os::arch::c95::c_int;
             use types::os::arch::posix88::mode_t;
 
-            pub const O_RDONLY : c_int = 0;
-            pub const O_WRONLY : c_int = 1;
-            pub const O_RDWR : c_int = 2;
-            pub const O_APPEND : c_int = 8;
-            pub const O_CREAT : c_int = 512;
-            pub const O_EXCL : c_int = 2048;
-            pub const O_NOCTTY : c_int = 131072;
-            pub const O_TRUNC : c_int = 1024;
-            pub const S_IFIFO : mode_t = 4096;
-            pub const S_IFCHR : mode_t = 8192;
-            pub const S_IFBLK : mode_t = 24576;
-            pub const S_IFDIR : mode_t = 16384;
-            pub const S_IFREG : mode_t = 32768;
-            pub const S_IFLNK : mode_t = 40960;
-            pub const S_IFSOCK : mode_t = 49152;
-            pub const S_IFMT : mode_t = 61440;
-            pub const S_IEXEC : mode_t = 64;
-            pub const S_IWRITE : mode_t = 128;
-            pub const S_IREAD : mode_t = 256;
-            pub const S_IRWXU : mode_t = 448;
-            pub const S_IXUSR : mode_t = 64;
-            pub const S_IWUSR : mode_t = 128;
-            pub const S_IRUSR : mode_t = 256;
-            pub const S_IRWXG : mode_t = 56;
-            pub const S_IXGRP : mode_t = 8;
-            pub const S_IWGRP : mode_t = 16;
-            pub const S_IRGRP : mode_t = 32;
-            pub const S_IRWXO : mode_t = 7;
-            pub const S_IXOTH : mode_t = 1;
-            pub const S_IWOTH : mode_t = 2;
-            pub const S_IROTH : mode_t = 4;
-            pub const F_OK : c_int = 0;
-            pub const R_OK : c_int = 4;
-            pub const W_OK : c_int = 2;
-            pub const X_OK : c_int = 1;
-            pub const STDIN_FILENO : c_int = 0;
-            pub const STDOUT_FILENO : c_int = 1;
-            pub const STDERR_FILENO : c_int = 2;
-            pub const F_LOCK : c_int = 1;
-            pub const F_TEST : c_int = 3;
-            pub const F_TLOCK : c_int = 2;
-            pub const F_ULOCK : c_int = 0;
-            pub const SIGHUP : c_int = 1;
-            pub const SIGINT : c_int = 2;
-            pub const SIGQUIT : c_int = 3;
-            pub const SIGILL : c_int = 4;
-            pub const SIGABRT : c_int = 6;
-            pub const SIGFPE : c_int = 8;
-            pub const SIGKILL : c_int = 9;
-            pub const SIGSEGV : c_int = 11;
-            pub const SIGPIPE : c_int = 13;
-            pub const SIGALRM : c_int = 14;
-            pub const SIGTERM : c_int = 15;
-
-            pub const PROT_NONE : c_int = 0;
-            pub const PROT_READ : c_int = 1;
-            pub const PROT_WRITE : c_int = 2;
-            pub const PROT_EXEC : c_int = 4;
-
-            pub const MAP_FILE : c_int = 0x0000;
-            pub const MAP_SHARED : c_int = 0x0001;
-            pub const MAP_PRIVATE : c_int = 0x0002;
-            pub const MAP_FIXED : c_int = 0x0010;
-            pub const MAP_ANON : c_int = 0x1000;
-
-            pub const MAP_FAILED : *mut c_void = !0 as *mut c_void;
-
-            pub const MCL_CURRENT : c_int = 0x0001;
-            pub const MCL_FUTURE : c_int = 0x0002;
-
-            pub const MS_ASYNC : c_int = 0x0001;
-            pub const MS_INVALIDATE : c_int = 0x0002;
-            pub const MS_SYNC : c_int = 0x0010;
-
-            pub const MS_KILLPAGES : c_int = 0x0004;
-            pub const MS_DEACTIVATE : c_int = 0x0008;
-
-            pub const EPERM : c_int = 1;
-            pub const ENOENT : c_int = 2;
-            pub const ESRCH : c_int = 3;
-            pub const EINTR : c_int = 4;
-            pub const EIO : c_int = 5;
-            pub const ENXIO : c_int = 6;
-            pub const E2BIG : c_int = 7;
-            pub const ENOEXEC : c_int = 8;
-            pub const EBADF : c_int = 9;
-            pub const ECHILD : c_int = 10;
-            pub const EDEADLK : c_int = 11;
-            pub const ENOMEM : c_int = 12;
-            pub const EACCES : c_int = 13;
-            pub const EFAULT : c_int = 14;
-            pub const ENOTBLK : c_int = 15;
-            pub const EBUSY : c_int = 16;
-            pub const EEXIST : c_int = 17;
-            pub const EXDEV : c_int = 18;
-            pub const ENODEV : c_int = 19;
-            pub const ENOTDIR : c_int = 20;
-            pub const EISDIR : c_int = 21;
-            pub const EINVAL : c_int = 22;
-            pub const ENFILE : c_int = 23;
-            pub const EMFILE : c_int = 24;
-            pub const ENOTTY : c_int = 25;
-            pub const ETXTBSY : c_int = 26;
-            pub const EFBIG : c_int = 27;
-            pub const ENOSPC : c_int = 28;
-            pub const ESPIPE : c_int = 29;
-            pub const EROFS : c_int = 30;
-            pub const EMLINK : c_int = 31;
-            pub const EPIPE : c_int = 32;
-            pub const EDOM : c_int = 33;
-            pub const ERANGE : c_int = 34;
-            pub const EAGAIN : c_int = 35;
-            pub const EWOULDBLOCK : c_int = EAGAIN;
-            pub const EINPROGRESS : c_int = 36;
-            pub const EALREADY : c_int = 37;
-            pub const ENOTSOCK : c_int = 38;
-            pub const EDESTADDRREQ : c_int = 39;
-            pub const EMSGSIZE : c_int = 40;
-            pub const EPROTOTYPE : c_int = 41;
-            pub const ENOPROTOOPT : c_int = 42;
-            pub const EPROTONOSUPPORT : c_int = 43;
-            pub const ESOCKTNOSUPPORT : c_int = 44;
-            pub const ENOTSUP : c_int = 45;
-            pub const EPFNOSUPPORT : c_int = 46;
-            pub const EAFNOSUPPORT : c_int = 47;
-            pub const EADDRINUSE : c_int = 48;
-            pub const EADDRNOTAVAIL : c_int = 49;
-            pub const ENETDOWN : c_int = 50;
-            pub const ENETUNREACH : c_int = 51;
-            pub const ENETRESET : c_int = 52;
-            pub const ECONNABORTED : c_int = 53;
-            pub const ECONNRESET : c_int = 54;
-            pub const ENOBUFS : c_int = 55;
-            pub const EISCONN : c_int = 56;
-            pub const ENOTCONN : c_int = 57;
-            pub const ESHUTDOWN : c_int = 58;
-            pub const ETOOMANYREFS : c_int = 59;
-            pub const ETIMEDOUT : c_int = 60;
-            pub const ECONNREFUSED : c_int = 61;
-            pub const ELOOP : c_int = 62;
-            pub const ENAMETOOLONG : c_int = 63;
-            pub const EHOSTDOWN : c_int = 64;
-            pub const EHOSTUNREACH : c_int = 65;
-            pub const ENOTEMPTY : c_int = 66;
-            pub const EPROCLIM : c_int = 67;
-            pub const EUSERS : c_int = 68;
-            pub const EDQUOT : c_int = 69;
-            pub const ESTALE : c_int = 70;
-            pub const EREMOTE : c_int = 71;
-            pub const EBADRPC : c_int = 72;
-            pub const ERPCMISMATCH : c_int = 73;
-            pub const EPROGUNAVAIL : c_int = 74;
-            pub const EPROGMISMATCH : c_int = 75;
-            pub const EPROCUNAVAIL : c_int = 76;
-            pub const ENOLCK : c_int = 77;
-            pub const ENOSYS : c_int = 78;
-            pub const EFTYPE : c_int = 79;
-            pub const EAUTH : c_int = 80;
-            pub const ENEEDAUTH : c_int = 81;
-            pub const EPWROFF : c_int = 82;
-            pub const EDEVERR : c_int = 83;
-            pub const EOVERFLOW : c_int = 84;
-            pub const EBADEXEC : c_int = 85;
-            pub const EBADARCH : c_int = 86;
-            pub const ESHLIBVERS : c_int = 87;
-            pub const EBADMACHO : c_int = 88;
-            pub const ECANCELED : c_int = 89;
-            pub const EIDRM : c_int = 90;
-            pub const ENOMSG : c_int = 91;
-            pub const EILSEQ : c_int = 92;
-            pub const ENOATTR : c_int = 93;
-            pub const EBADMSG : c_int = 94;
-            pub const EMULTIHOP : c_int = 95;
-            pub const ENODATA : c_int = 96;
-            pub const ENOLINK : c_int = 97;
-            pub const ENOSR : c_int = 98;
-            pub const ENOSTR : c_int = 99;
-            pub const EPROTO : c_int = 100;
-            pub const ETIME : c_int = 101;
-            pub const EOPNOTSUPP : c_int = 102;
-            pub const ENOPOLICY : c_int = 103;
-            pub const ENOTRECOVERABLE : c_int = 104;
-            pub const EOWNERDEAD : c_int = 105;
-            pub const EQFULL : c_int = 106;
-            pub const ELAST : c_int = 106;
+            pub const O_RDONLY: c_int = 0;
+            pub const O_WRONLY: c_int = 1;
+            pub const O_RDWR: c_int = 2;
+            pub const O_APPEND: c_int = 8;
+            pub const O_CREAT: c_int = 512;
+            pub const O_EXCL: c_int = 2048;
+            pub const O_NOCTTY: c_int = 131072;
+            pub const O_TRUNC: c_int = 1024;
+            pub const S_IFIFO: mode_t = 4096;
+            pub const S_IFCHR: mode_t = 8192;
+            pub const S_IFBLK: mode_t = 24576;
+            pub const S_IFDIR: mode_t = 16384;
+            pub const S_IFREG: mode_t = 32768;
+            pub const S_IFLNK: mode_t = 40960;
+            pub const S_IFSOCK: mode_t = 49152;
+            pub const S_IFMT: mode_t = 61440;
+            pub const S_IEXEC: mode_t = 64;
+            pub const S_IWRITE: mode_t = 128;
+            pub const S_IREAD: mode_t = 256;
+            pub const S_IRWXU: mode_t = 448;
+            pub const S_IXUSR: mode_t = 64;
+            pub const S_IWUSR: mode_t = 128;
+            pub const S_IRUSR: mode_t = 256;
+            pub const S_IRWXG: mode_t = 56;
+            pub const S_IXGRP: mode_t = 8;
+            pub const S_IWGRP: mode_t = 16;
+            pub const S_IRGRP: mode_t = 32;
+            pub const S_IRWXO: mode_t = 7;
+            pub const S_IXOTH: mode_t = 1;
+            pub const S_IWOTH: mode_t = 2;
+            pub const S_IROTH: mode_t = 4;
+            pub const F_OK: c_int = 0;
+            pub const R_OK: c_int = 4;
+            pub const W_OK: c_int = 2;
+            pub const X_OK: c_int = 1;
+            pub const STDIN_FILENO: c_int = 0;
+            pub const STDOUT_FILENO: c_int = 1;
+            pub const STDERR_FILENO: c_int = 2;
+            pub const F_LOCK: c_int = 1;
+            pub const F_TEST: c_int = 3;
+            pub const F_TLOCK: c_int = 2;
+            pub const F_ULOCK: c_int = 0;
+            pub const SIGHUP: c_int = 1;
+            pub const SIGINT: c_int = 2;
+            pub const SIGQUIT: c_int = 3;
+            pub const SIGILL: c_int = 4;
+            pub const SIGABRT: c_int = 6;
+            pub const SIGFPE: c_int = 8;
+            pub const SIGKILL: c_int = 9;
+            pub const SIGSEGV: c_int = 11;
+            pub const SIGPIPE: c_int = 13;
+            pub const SIGALRM: c_int = 14;
+            pub const SIGTERM: c_int = 15;
+
+            pub const PROT_NONE: c_int = 0;
+            pub const PROT_READ: c_int = 1;
+            pub const PROT_WRITE: c_int = 2;
+            pub const PROT_EXEC: c_int = 4;
+
+            pub const MAP_FILE: c_int = 0x0000;
+            pub const MAP_SHARED: c_int = 0x0001;
+            pub const MAP_PRIVATE: c_int = 0x0002;
+            pub const MAP_FIXED: c_int = 0x0010;
+            pub const MAP_ANON: c_int = 0x1000;
+
+            pub const MAP_FAILED: *mut c_void = !0 as *mut c_void;
+
+            pub const MCL_CURRENT: c_int = 0x0001;
+            pub const MCL_FUTURE: c_int = 0x0002;
+
+            pub const MS_ASYNC: c_int = 0x0001;
+            pub const MS_INVALIDATE: c_int = 0x0002;
+            pub const MS_SYNC: c_int = 0x0010;
+
+            pub const MS_KILLPAGES: c_int = 0x0004;
+            pub const MS_DEACTIVATE: c_int = 0x0008;
+
+            pub const EPERM: c_int = 1;
+            pub const ENOENT: c_int = 2;
+            pub const ESRCH: c_int = 3;
+            pub const EINTR: c_int = 4;
+            pub const EIO: c_int = 5;
+            pub const ENXIO: c_int = 6;
+            pub const E2BIG: c_int = 7;
+            pub const ENOEXEC: c_int = 8;
+            pub const EBADF: c_int = 9;
+            pub const ECHILD: c_int = 10;
+            pub const EDEADLK: c_int = 11;
+            pub const ENOMEM: c_int = 12;
+            pub const EACCES: c_int = 13;
+            pub const EFAULT: c_int = 14;
+            pub const ENOTBLK: c_int = 15;
+            pub const EBUSY: c_int = 16;
+            pub const EEXIST: c_int = 17;
+            pub const EXDEV: c_int = 18;
+            pub const ENODEV: c_int = 19;
+            pub const ENOTDIR: c_int = 20;
+            pub const EISDIR: c_int = 21;
+            pub const EINVAL: c_int = 22;
+            pub const ENFILE: c_int = 23;
+            pub const EMFILE: c_int = 24;
+            pub const ENOTTY: c_int = 25;
+            pub const ETXTBSY: c_int = 26;
+            pub const EFBIG: c_int = 27;
+            pub const ENOSPC: c_int = 28;
+            pub const ESPIPE: c_int = 29;
+            pub const EROFS: c_int = 30;
+            pub const EMLINK: c_int = 31;
+            pub const EPIPE: c_int = 32;
+            pub const EDOM: c_int = 33;
+            pub const ERANGE: c_int = 34;
+            pub const EAGAIN: c_int = 35;
+            pub const EWOULDBLOCK: c_int = EAGAIN;
+            pub const EINPROGRESS: c_int = 36;
+            pub const EALREADY: c_int = 37;
+            pub const ENOTSOCK: c_int = 38;
+            pub const EDESTADDRREQ: c_int = 39;
+            pub const EMSGSIZE: c_int = 40;
+            pub const EPROTOTYPE: c_int = 41;
+            pub const ENOPROTOOPT: c_int = 42;
+            pub const EPROTONOSUPPORT: c_int = 43;
+            pub const ESOCKTNOSUPPORT: c_int = 44;
+            pub const ENOTSUP: c_int = 45;
+            pub const EPFNOSUPPORT: c_int = 46;
+            pub const EAFNOSUPPORT: c_int = 47;
+            pub const EADDRINUSE: c_int = 48;
+            pub const EADDRNOTAVAIL: c_int = 49;
+            pub const ENETDOWN: c_int = 50;
+            pub const ENETUNREACH: c_int = 51;
+            pub const ENETRESET: c_int = 52;
+            pub const ECONNABORTED: c_int = 53;
+            pub const ECONNRESET: c_int = 54;
+            pub const ENOBUFS: c_int = 55;
+            pub const EISCONN: c_int = 56;
+            pub const ENOTCONN: c_int = 57;
+            pub const ESHUTDOWN: c_int = 58;
+            pub const ETOOMANYREFS: c_int = 59;
+            pub const ETIMEDOUT: c_int = 60;
+            pub const ECONNREFUSED: c_int = 61;
+            pub const ELOOP: c_int = 62;
+            pub const ENAMETOOLONG: c_int = 63;
+            pub const EHOSTDOWN: c_int = 64;
+            pub const EHOSTUNREACH: c_int = 65;
+            pub const ENOTEMPTY: c_int = 66;
+            pub const EPROCLIM: c_int = 67;
+            pub const EUSERS: c_int = 68;
+            pub const EDQUOT: c_int = 69;
+            pub const ESTALE: c_int = 70;
+            pub const EREMOTE: c_int = 71;
+            pub const EBADRPC: c_int = 72;
+            pub const ERPCMISMATCH: c_int = 73;
+            pub const EPROGUNAVAIL: c_int = 74;
+            pub const EPROGMISMATCH: c_int = 75;
+            pub const EPROCUNAVAIL: c_int = 76;
+            pub const ENOLCK: c_int = 77;
+            pub const ENOSYS: c_int = 78;
+            pub const EFTYPE: c_int = 79;
+            pub const EAUTH: c_int = 80;
+            pub const ENEEDAUTH: c_int = 81;
+            pub const EPWROFF: c_int = 82;
+            pub const EDEVERR: c_int = 83;
+            pub const EOVERFLOW: c_int = 84;
+            pub const EBADEXEC: c_int = 85;
+            pub const EBADARCH: c_int = 86;
+            pub const ESHLIBVERS: c_int = 87;
+            pub const EBADMACHO: c_int = 88;
+            pub const ECANCELED: c_int = 89;
+            pub const EIDRM: c_int = 90;
+            pub const ENOMSG: c_int = 91;
+            pub const EILSEQ: c_int = 92;
+            pub const ENOATTR: c_int = 93;
+            pub const EBADMSG: c_int = 94;
+            pub const EMULTIHOP: c_int = 95;
+            pub const ENODATA: c_int = 96;
+            pub const ENOLINK: c_int = 97;
+            pub const ENOSR: c_int = 98;
+            pub const ENOSTR: c_int = 99;
+            pub const EPROTO: c_int = 100;
+            pub const ETIME: c_int = 101;
+            pub const EOPNOTSUPP: c_int = 102;
+            pub const ENOPOLICY: c_int = 103;
+            pub const ENOTRECOVERABLE: c_int = 104;
+            pub const EOWNERDEAD: c_int = 105;
+            pub const EQFULL: c_int = 106;
+            pub const ELAST: c_int = 106;
         }
         pub mod posix01 {
             use types::os::arch::c95::{c_int, size_t};
             use types::os::common::posix01::rlim_t;
 
-            pub const F_DUPFD : c_int = 0;
-            pub const F_GETFD : c_int = 1;
-            pub const F_SETFD : c_int = 2;
-            pub const F_GETFL : c_int = 3;
-            pub const F_SETFL : c_int = 4;
+            pub const F_DUPFD: c_int = 0;
+            pub const F_GETFD: c_int = 1;
+            pub const F_SETFD: c_int = 2;
+            pub const F_GETFL: c_int = 3;
+            pub const F_SETFL: c_int = 4;
 
-            pub const O_ACCMODE : c_int = 3;
+            pub const O_ACCMODE: c_int = 3;
 
-            pub const SIGTRAP : c_int = 5;
+            pub const SIGTRAP: c_int = 5;
             pub const SIG_IGN: size_t = 1;
 
-            pub const GLOB_APPEND   : c_int = 0x0001;
-            pub const GLOB_DOOFFS   : c_int = 0x0002;
-            pub const GLOB_ERR      : c_int = 0x0004;
-            pub const GLOB_MARK     : c_int = 0x0008;
-            pub const GLOB_NOCHECK  : c_int = 0x0010;
-            pub const GLOB_NOSORT   : c_int = 0x0020;
-            pub const GLOB_NOESCAPE : c_int = 0x2000;
-
-            pub const GLOB_NOSPACE  : c_int = -1;
-            pub const GLOB_ABORTED  : c_int = -2;
-            pub const GLOB_NOMATCH  : c_int = -3;
-
-            pub const POSIX_MADV_NORMAL : c_int = 0;
-            pub const POSIX_MADV_RANDOM : c_int = 1;
-            pub const POSIX_MADV_SEQUENTIAL : c_int = 2;
-            pub const POSIX_MADV_WILLNEED : c_int = 3;
-            pub const POSIX_MADV_DONTNEED : c_int = 4;
-
-            pub const _SC_IOV_MAX : c_int = 56;
-            pub const _SC_GETGR_R_SIZE_MAX : c_int = 70;
-            pub const _SC_GETPW_R_SIZE_MAX : c_int = 71;
-            pub const _SC_LOGIN_NAME_MAX : c_int = 73;
-            pub const _SC_MQ_PRIO_MAX : c_int = 75;
-            pub const _SC_THREAD_ATTR_STACKADDR : c_int = 82;
-            pub const _SC_THREAD_ATTR_STACKSIZE : c_int = 83;
-            pub const _SC_THREAD_DESTRUCTOR_ITERATIONS : c_int = 85;
-            pub const _SC_THREAD_KEYS_MAX : c_int = 86;
-            pub const _SC_THREAD_PRIO_INHERIT : c_int = 87;
-            pub const _SC_THREAD_PRIO_PROTECT : c_int = 88;
-            pub const _SC_THREAD_PRIORITY_SCHEDULING : c_int = 89;
-            pub const _SC_THREAD_PROCESS_SHARED : c_int = 90;
-            pub const _SC_THREAD_SAFE_FUNCTIONS : c_int = 91;
-            pub const _SC_THREAD_STACK_MIN : c_int = 93;
-            pub const _SC_THREAD_THREADS_MAX : c_int = 94;
-            pub const _SC_THREADS : c_int = 96;
-            pub const _SC_TTY_NAME_MAX : c_int = 101;
-            pub const _SC_ATEXIT_MAX : c_int = 107;
-            pub const _SC_XOPEN_CRYPT : c_int = 108;
-            pub const _SC_XOPEN_ENH_I18N : c_int = 109;
-            pub const _SC_XOPEN_LEGACY : c_int = 110;
-            pub const _SC_XOPEN_REALTIME : c_int = 111;
-            pub const _SC_XOPEN_REALTIME_THREADS : c_int = 112;
-            pub const _SC_XOPEN_SHM : c_int = 113;
-            pub const _SC_XOPEN_UNIX : c_int = 115;
-            pub const _SC_XOPEN_VERSION : c_int = 116;
-            pub const _SC_XOPEN_XCU_VERSION : c_int = 121;
+            pub const GLOB_APPEND: c_int = 0x0001;
+            pub const GLOB_DOOFFS: c_int = 0x0002;
+            pub const GLOB_ERR: c_int = 0x0004;
+            pub const GLOB_MARK: c_int = 0x0008;
+            pub const GLOB_NOCHECK: c_int = 0x0010;
+            pub const GLOB_NOSORT: c_int = 0x0020;
+            pub const GLOB_NOESCAPE: c_int = 0x2000;
+
+            pub const GLOB_NOSPACE: c_int = -1;
+            pub const GLOB_ABORTED: c_int = -2;
+            pub const GLOB_NOMATCH: c_int = -3;
+
+            pub const POSIX_MADV_NORMAL: c_int = 0;
+            pub const POSIX_MADV_RANDOM: c_int = 1;
+            pub const POSIX_MADV_SEQUENTIAL: c_int = 2;
+            pub const POSIX_MADV_WILLNEED: c_int = 3;
+            pub const POSIX_MADV_DONTNEED: c_int = 4;
+
+            pub const _SC_IOV_MAX: c_int = 56;
+            pub const _SC_GETGR_R_SIZE_MAX: c_int = 70;
+            pub const _SC_GETPW_R_SIZE_MAX: c_int = 71;
+            pub const _SC_LOGIN_NAME_MAX: c_int = 73;
+            pub const _SC_MQ_PRIO_MAX: c_int = 75;
+            pub const _SC_THREAD_ATTR_STACKADDR: c_int = 82;
+            pub const _SC_THREAD_ATTR_STACKSIZE: c_int = 83;
+            pub const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 85;
+            pub const _SC_THREAD_KEYS_MAX: c_int = 86;
+            pub const _SC_THREAD_PRIO_INHERIT: c_int = 87;
+            pub const _SC_THREAD_PRIO_PROTECT: c_int = 88;
+            pub const _SC_THREAD_PRIORITY_SCHEDULING: c_int = 89;
+            pub const _SC_THREAD_PROCESS_SHARED: c_int = 90;
+            pub const _SC_THREAD_SAFE_FUNCTIONS: c_int = 91;
+            pub const _SC_THREAD_STACK_MIN: c_int = 93;
+            pub const _SC_THREAD_THREADS_MAX: c_int = 94;
+            pub const _SC_THREADS: c_int = 96;
+            pub const _SC_TTY_NAME_MAX: c_int = 101;
+            pub const _SC_ATEXIT_MAX: c_int = 107;
+            pub const _SC_XOPEN_CRYPT: c_int = 108;
+            pub const _SC_XOPEN_ENH_I18N: c_int = 109;
+            pub const _SC_XOPEN_LEGACY: c_int = 110;
+            pub const _SC_XOPEN_REALTIME: c_int = 111;
+            pub const _SC_XOPEN_REALTIME_THREADS: c_int = 112;
+            pub const _SC_XOPEN_SHM: c_int = 113;
+            pub const _SC_XOPEN_UNIX: c_int = 115;
+            pub const _SC_XOPEN_VERSION: c_int = 116;
+            pub const _SC_XOPEN_XCU_VERSION: c_int = 121;
 
             pub const PTHREAD_CREATE_JOINABLE: c_int = 1;
             pub const PTHREAD_CREATE_DETACHED: c_int = 2;
@@ -5195,22 +5850,22 @@ pub mod consts {
         pub mod bsd44 {
             use types::os::arch::c95::c_int;
 
-            pub const MADV_NORMAL : c_int = 0;
-            pub const MADV_RANDOM : c_int = 1;
-            pub const MADV_SEQUENTIAL : c_int = 2;
-            pub const MADV_WILLNEED : c_int = 3;
-            pub const MADV_DONTNEED : c_int = 4;
-            pub const MADV_FREE : c_int = 5;
-            pub const MADV_ZERO_WIRED_PAGES : c_int = 6;
-            pub const MADV_FREE_REUSABLE : c_int = 7;
-            pub const MADV_FREE_REUSE : c_int = 8;
-            pub const MADV_CAN_REUSE : c_int = 9;
-
-            pub const MINCORE_INCORE : c_int =  0x1;
-            pub const MINCORE_REFERENCED : c_int = 0x2;
-            pub const MINCORE_MODIFIED : c_int = 0x4;
-            pub const MINCORE_REFERENCED_OTHER : c_int = 0x8;
-            pub const MINCORE_MODIFIED_OTHER : c_int = 0x10;
+            pub const MADV_NORMAL: c_int = 0;
+            pub const MADV_RANDOM: c_int = 1;
+            pub const MADV_SEQUENTIAL: c_int = 2;
+            pub const MADV_WILLNEED: c_int = 3;
+            pub const MADV_DONTNEED: c_int = 4;
+            pub const MADV_FREE: c_int = 5;
+            pub const MADV_ZERO_WIRED_PAGES: c_int = 6;
+            pub const MADV_FREE_REUSABLE: c_int = 7;
+            pub const MADV_FREE_REUSE: c_int = 8;
+            pub const MADV_CAN_REUSE: c_int = 9;
+
+            pub const MINCORE_INCORE: c_int = 0x1;
+            pub const MINCORE_REFERENCED: c_int = 0x2;
+            pub const MINCORE_MODIFIED: c_int = 0x4;
+            pub const MINCORE_REFERENCED_OTHER: c_int = 0x8;
+            pub const MINCORE_MODIFIED_OTHER: c_int = 0x10;
 
             pub const AF_UNIX: c_int = 1;
             pub const AF_INET: c_int = 2;
@@ -5267,22 +5922,22 @@ pub mod consts {
         pub mod extra {
             use types::os::arch::c95::c_int;
 
-            pub const O_DSYNC : c_int = 4194304;
-            pub const O_SYNC : c_int = 128;
-            pub const O_NONBLOCK : c_int = 4;
-            pub const F_GETPATH : c_int = 50;
-            pub const F_FULLFSYNC : c_int = 51;
+            pub const O_DSYNC: c_int = 4194304;
+            pub const O_SYNC: c_int = 128;
+            pub const O_NONBLOCK: c_int = 4;
+            pub const F_GETPATH: c_int = 50;
+            pub const F_FULLFSYNC: c_int = 51;
+
+            pub const MAP_COPY: c_int = 0x0002;
+            pub const MAP_RENAME: c_int = 0x0020;
+            pub const MAP_NORESERVE: c_int = 0x0040;
+            pub const MAP_NOEXTEND: c_int = 0x0100;
+            pub const MAP_HASSEMAPHORE: c_int = 0x0200;
+            pub const MAP_NOCACHE: c_int = 0x0400;
+            pub const MAP_JIT: c_int = 0x0800;
+            pub const MAP_STACK: c_int = 0;
 
-            pub const MAP_COPY : c_int = 0x0002;
-            pub const MAP_RENAME : c_int = 0x0020;
-            pub const MAP_NORESERVE : c_int = 0x0040;
-            pub const MAP_NOEXTEND : c_int = 0x0100;
-            pub const MAP_HASSEMAPHORE : c_int = 0x0200;
-            pub const MAP_NOCACHE : c_int = 0x0400;
-            pub const MAP_JIT : c_int = 0x0800;
-            pub const MAP_STACK : c_int = 0;
-
-            pub const IPPROTO_RAW : c_int = 255;
+            pub const IPPROTO_RAW: c_int = 255;
 
             pub const SO_NREAD: c_int = 0x1020;
             pub const SO_NKE: c_int = 0x1021;
@@ -5298,106 +5953,106 @@ pub mod consts {
         pub mod sysconf {
             use types::os::arch::c95::c_int;
 
-            pub const _SC_ARG_MAX : c_int = 1;
-            pub const _SC_CHILD_MAX : c_int = 2;
-            pub const _SC_CLK_TCK : c_int = 3;
-            pub const _SC_NGROUPS_MAX : c_int = 4;
-            pub const _SC_OPEN_MAX : c_int = 5;
-            pub const _SC_JOB_CONTROL : c_int = 6;
-            pub const _SC_SAVED_IDS : c_int = 7;
-            pub const _SC_VERSION : c_int = 8;
-            pub const _SC_BC_BASE_MAX : c_int = 9;
-            pub const _SC_BC_DIM_MAX : c_int = 10;
-            pub const _SC_BC_SCALE_MAX : c_int = 11;
-            pub const _SC_BC_STRING_MAX : c_int = 12;
-            pub const _SC_COLL_WEIGHTS_MAX : c_int = 13;
-            pub const _SC_EXPR_NEST_MAX : c_int = 14;
-            pub const _SC_LINE_MAX : c_int = 15;
-            pub const _SC_RE_DUP_MAX : c_int = 16;
-            pub const _SC_2_VERSION : c_int = 17;
-            pub const _SC_2_C_BIND : c_int = 18;
-            pub const _SC_2_C_DEV : c_int = 19;
-            pub const _SC_2_CHAR_TERM : c_int = 20;
-            pub const _SC_2_FORT_DEV : c_int = 21;
-            pub const _SC_2_FORT_RUN : c_int = 22;
-            pub const _SC_2_LOCALEDEF : c_int = 23;
-            pub const _SC_2_SW_DEV : c_int = 24;
-            pub const _SC_2_UPE : c_int = 25;
-            pub const _SC_STREAM_MAX : c_int = 26;
-            pub const _SC_TZNAME_MAX : c_int = 27;
-            pub const _SC_ASYNCHRONOUS_IO : c_int = 28;
-            pub const _SC_PAGESIZE : c_int = 29;
-            pub const _SC_MEMLOCK : c_int = 30;
-            pub const _SC_MEMLOCK_RANGE : c_int = 31;
-            pub const _SC_MEMORY_PROTECTION : c_int = 32;
-            pub const _SC_MESSAGE_PASSING : c_int = 33;
-            pub const _SC_PRIORITIZED_IO : c_int = 34;
-            pub const _SC_PRIORITY_SCHEDULING : c_int = 35;
-            pub const _SC_REALTIME_SIGNALS : c_int = 36;
-            pub const _SC_SEMAPHORES : c_int = 37;
-            pub const _SC_FSYNC : c_int = 38;
-            pub const _SC_SHARED_MEMORY_OBJECTS : c_int = 39;
-            pub const _SC_SYNCHRONIZED_IO : c_int = 40;
-            pub const _SC_TIMERS : c_int = 41;
-            pub const _SC_AIO_LISTIO_MAX : c_int = 42;
-            pub const _SC_AIO_MAX : c_int = 43;
-            pub const _SC_AIO_PRIO_DELTA_MAX : c_int = 44;
-            pub const _SC_DELAYTIMER_MAX : c_int = 45;
-            pub const _SC_MQ_OPEN_MAX : c_int = 46;
-            pub const _SC_MAPPED_FILES : c_int = 47;
-            pub const _SC_RTSIG_MAX : c_int = 48;
-            pub const _SC_SEM_NSEMS_MAX : c_int = 49;
-            pub const _SC_SEM_VALUE_MAX : c_int = 50;
-            pub const _SC_SIGQUEUE_MAX : c_int = 51;
-            pub const _SC_TIMER_MAX : c_int = 52;
-            pub const _SC_NPROCESSORS_CONF : c_int = 57;
-            pub const _SC_NPROCESSORS_ONLN : c_int = 58;
-            pub const _SC_2_PBS : c_int = 59;
-            pub const _SC_2_PBS_ACCOUNTING : c_int = 60;
-            pub const _SC_2_PBS_CHECKPOINT : c_int = 61;
-            pub const _SC_2_PBS_LOCATE : c_int = 62;
-            pub const _SC_2_PBS_MESSAGE : c_int = 63;
-            pub const _SC_2_PBS_TRACK : c_int = 64;
-            pub const _SC_ADVISORY_INFO : c_int = 65;
-            pub const _SC_BARRIERS : c_int = 66;
-            pub const _SC_CLOCK_SELECTION : c_int = 67;
-            pub const _SC_CPUTIME : c_int = 68;
-            pub const _SC_FILE_LOCKING : c_int = 69;
-            pub const _SC_HOST_NAME_MAX : c_int = 72;
-            pub const _SC_MONOTONIC_CLOCK : c_int = 74;
-            pub const _SC_READER_WRITER_LOCKS : c_int = 76;
-            pub const _SC_REGEXP : c_int = 77;
-            pub const _SC_SHELL : c_int = 78;
-            pub const _SC_SPAWN : c_int = 79;
-            pub const _SC_SPIN_LOCKS : c_int = 80;
-            pub const _SC_SPORADIC_SERVER : c_int = 81;
-            pub const _SC_THREAD_CPUTIME : c_int = 84;
-            pub const _SC_THREAD_SPORADIC_SERVER : c_int = 92;
-            pub const _SC_TIMEOUTS : c_int = 95;
-            pub const _SC_TRACE : c_int = 97;
-            pub const _SC_TRACE_EVENT_FILTER : c_int = 98;
-            pub const _SC_TRACE_INHERIT : c_int = 99;
-            pub const _SC_TRACE_LOG : c_int = 100;
-            pub const _SC_TYPED_MEMORY_OBJECTS : c_int = 102;
-            pub const _SC_V6_ILP32_OFF32 : c_int = 103;
-            pub const _SC_V6_ILP32_OFFBIG : c_int = 104;
-            pub const _SC_V6_LP64_OFF64 : c_int = 105;
-            pub const _SC_V6_LPBIG_OFFBIG : c_int = 106;
-            pub const _SC_IPV6 : c_int = 118;
-            pub const _SC_RAW_SOCKETS : c_int = 119;
-            pub const _SC_SYMLOOP_MAX : c_int = 120;
-            pub const _SC_PAGE_SIZE : c_int = _SC_PAGESIZE;
-            pub const _SC_XOPEN_STREAMS : c_int = 114;
-            pub const _SC_XBS5_ILP32_OFF32 : c_int = 122;
-            pub const _SC_XBS5_ILP32_OFFBIG : c_int = 123;
-            pub const _SC_XBS5_LP64_OFF64 : c_int = 124;
-            pub const _SC_XBS5_LPBIG_OFFBIG : c_int = 125;
-            pub const _SC_SS_REPL_MAX : c_int = 126;
-            pub const _SC_TRACE_EVENT_NAME_MAX : c_int = 127;
-            pub const _SC_TRACE_NAME_MAX : c_int = 128;
-            pub const _SC_TRACE_SYS_MAX : c_int = 129;
-            pub const _SC_TRACE_USER_EVENT_MAX : c_int = 130;
-            pub const _SC_PASS_MAX : c_int = 131;
+            pub const _SC_ARG_MAX: c_int = 1;
+            pub const _SC_CHILD_MAX: c_int = 2;
+            pub const _SC_CLK_TCK: c_int = 3;
+            pub const _SC_NGROUPS_MAX: c_int = 4;
+            pub const _SC_OPEN_MAX: c_int = 5;
+            pub const _SC_JOB_CONTROL: c_int = 6;
+            pub const _SC_SAVED_IDS: c_int = 7;
+            pub const _SC_VERSION: c_int = 8;
+            pub const _SC_BC_BASE_MAX: c_int = 9;
+            pub const _SC_BC_DIM_MAX: c_int = 10;
+            pub const _SC_BC_SCALE_MAX: c_int = 11;
+            pub const _SC_BC_STRING_MAX: c_int = 12;
+            pub const _SC_COLL_WEIGHTS_MAX: c_int = 13;
+            pub const _SC_EXPR_NEST_MAX: c_int = 14;
+            pub const _SC_LINE_MAX: c_int = 15;
+            pub const _SC_RE_DUP_MAX: c_int = 16;
+            pub const _SC_2_VERSION: c_int = 17;
+            pub const _SC_2_C_BIND: c_int = 18;
+            pub const _SC_2_C_DEV: c_int = 19;
+            pub const _SC_2_CHAR_TERM: c_int = 20;
+            pub const _SC_2_FORT_DEV: c_int = 21;
+            pub const _SC_2_FORT_RUN: c_int = 22;
+            pub const _SC_2_LOCALEDEF: c_int = 23;
+            pub const _SC_2_SW_DEV: c_int = 24;
+            pub const _SC_2_UPE: c_int = 25;
+            pub const _SC_STREAM_MAX: c_int = 26;
+            pub const _SC_TZNAME_MAX: c_int = 27;
+            pub const _SC_ASYNCHRONOUS_IO: c_int = 28;
+            pub const _SC_PAGESIZE: c_int = 29;
+            pub const _SC_MEMLOCK: c_int = 30;
+            pub const _SC_MEMLOCK_RANGE: c_int = 31;
+            pub const _SC_MEMORY_PROTECTION: c_int = 32;
+            pub const _SC_MESSAGE_PASSING: c_int = 33;
+            pub const _SC_PRIORITIZED_IO: c_int = 34;
+            pub const _SC_PRIORITY_SCHEDULING: c_int = 35;
+            pub const _SC_REALTIME_SIGNALS: c_int = 36;
+            pub const _SC_SEMAPHORES: c_int = 37;
+            pub const _SC_FSYNC: c_int = 38;
+            pub const _SC_SHARED_MEMORY_OBJECTS: c_int = 39;
+            pub const _SC_SYNCHRONIZED_IO: c_int = 40;
+            pub const _SC_TIMERS: c_int = 41;
+            pub const _SC_AIO_LISTIO_MAX: c_int = 42;
+            pub const _SC_AIO_MAX: c_int = 43;
+            pub const _SC_AIO_PRIO_DELTA_MAX: c_int = 44;
+            pub const _SC_DELAYTIMER_MAX: c_int = 45;
+            pub const _SC_MQ_OPEN_MAX: c_int = 46;
+            pub const _SC_MAPPED_FILES: c_int = 47;
+            pub const _SC_RTSIG_MAX: c_int = 48;
+            pub const _SC_SEM_NSEMS_MAX: c_int = 49;
+            pub const _SC_SEM_VALUE_MAX: c_int = 50;
+            pub const _SC_SIGQUEUE_MAX: c_int = 51;
+            pub const _SC_TIMER_MAX: c_int = 52;
+            pub const _SC_NPROCESSORS_CONF: c_int = 57;
+            pub const _SC_NPROCESSORS_ONLN: c_int = 58;
+            pub const _SC_2_PBS: c_int = 59;
+            pub const _SC_2_PBS_ACCOUNTING: c_int = 60;
+            pub const _SC_2_PBS_CHECKPOINT: c_int = 61;
+            pub const _SC_2_PBS_LOCATE: c_int = 62;
+            pub const _SC_2_PBS_MESSAGE: c_int = 63;
+            pub const _SC_2_PBS_TRACK: c_int = 64;
+            pub const _SC_ADVISORY_INFO: c_int = 65;
+            pub const _SC_BARRIERS: c_int = 66;
+            pub const _SC_CLOCK_SELECTION: c_int = 67;
+            pub const _SC_CPUTIME: c_int = 68;
+            pub const _SC_FILE_LOCKING: c_int = 69;
+            pub const _SC_HOST_NAME_MAX: c_int = 72;
+            pub const _SC_MONOTONIC_CLOCK: c_int = 74;
+            pub const _SC_READER_WRITER_LOCKS: c_int = 76;
+            pub const _SC_REGEXP: c_int = 77;
+            pub const _SC_SHELL: c_int = 78;
+            pub const _SC_SPAWN: c_int = 79;
+            pub const _SC_SPIN_LOCKS: c_int = 80;
+            pub const _SC_SPORADIC_SERVER: c_int = 81;
+            pub const _SC_THREAD_CPUTIME: c_int = 84;
+            pub const _SC_THREAD_SPORADIC_SERVER: c_int = 92;
+            pub const _SC_TIMEOUTS: c_int = 95;
+            pub const _SC_TRACE: c_int = 97;
+            pub const _SC_TRACE_EVENT_FILTER: c_int = 98;
+            pub const _SC_TRACE_INHERIT: c_int = 99;
+            pub const _SC_TRACE_LOG: c_int = 100;
+            pub const _SC_TYPED_MEMORY_OBJECTS: c_int = 102;
+            pub const _SC_V6_ILP32_OFF32: c_int = 103;
+            pub const _SC_V6_ILP32_OFFBIG: c_int = 104;
+            pub const _SC_V6_LP64_OFF64: c_int = 105;
+            pub const _SC_V6_LPBIG_OFFBIG: c_int = 106;
+            pub const _SC_IPV6: c_int = 118;
+            pub const _SC_RAW_SOCKETS: c_int = 119;
+            pub const _SC_SYMLOOP_MAX: c_int = 120;
+            pub const _SC_PAGE_SIZE: c_int = _SC_PAGESIZE;
+            pub const _SC_XOPEN_STREAMS: c_int = 114;
+            pub const _SC_XBS5_ILP32_OFF32: c_int = 122;
+            pub const _SC_XBS5_ILP32_OFFBIG: c_int = 123;
+            pub const _SC_XBS5_LP64_OFF64: c_int = 124;
+            pub const _SC_XBS5_LPBIG_OFFBIG: c_int = 125;
+            pub const _SC_SS_REPL_MAX: c_int = 126;
+            pub const _SC_TRACE_EVENT_NAME_MAX: c_int = 127;
+            pub const _SC_TRACE_NAME_MAX: c_int = 128;
+            pub const _SC_TRACE_SYS_MAX: c_int = 129;
+            pub const _SC_TRACE_USER_EVENT_MAX: c_int = 130;
+            pub const _SC_PASS_MAX: c_int = 131;
 
             pub const _PC_NAME_MAX: c_int = 4;
             pub const _PC_PATH_MAX: c_int = 5;
@@ -5436,16 +6091,15 @@ pub mod funcs {
             use types::os::arch::c95::{c_char, c_int, c_long, size_t};
 
             extern {
-                pub fn fopen(filename: *const c_char,
-                             mode: *const c_char) -> *mut FILE;
-                pub fn freopen(filename: *const c_char, mode: *const c_char,
+                pub fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE;
+                pub fn freopen(filename: *const c_char,
+                               mode: *const c_char,
                                file: *mut FILE)
                                -> *mut FILE;
                 pub fn fflush(file: *mut FILE) -> c_int;
                 pub fn fclose(file: *mut FILE) -> c_int;
                 pub fn remove(filename: *const c_char) -> c_int;
-                pub fn rename(oldname: *const c_char,
-                              newname: *const c_char) -> c_int;
+                pub fn rename(oldname: *const c_char, newname: *const c_char) -> c_int;
                 pub fn tmpfile() -> *mut FILE;
                 pub fn setvbuf(stream: *mut FILE,
                                buffer: *mut c_char,
@@ -5455,10 +6109,9 @@ pub mod funcs {
                 pub fn setbuf(stream: *mut FILE, buf: *mut c_char);
                 // Omitted: printf and scanf variants.
                 pub fn fgetc(stream: *mut FILE) -> c_int;
-                pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE)
-                             -> *mut c_char;
+                pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char;
                 pub fn fputc(c: c_int, stream: *mut FILE) -> c_int;
-                pub fn fputs(s: *const c_char, stream: *mut FILE)-> c_int;
+                pub fn fputs(s: *const c_char, stream: *mut FILE) -> c_int;
                 // Omitted: getc, getchar (might be macros).
 
                 // Omitted: gets, so ridiculously unsafe that it should not
@@ -5477,8 +6130,7 @@ pub mod funcs {
                               nobj: size_t,
                               stream: *mut FILE)
                               -> size_t;
-                pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int)
-                             -> c_int;
+                pub fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int;
                 pub fn ftell(stream: *mut FILE) -> c_long;
                 pub fn rewind(stream: *mut FILE);
                 pub fn fgetpos(stream: *mut FILE, ptr: *mut fpos_t) -> c_int;
@@ -5493,7 +6145,7 @@ pub mod funcs {
             use types::common::c95::c_void;
             use types::os::arch::c95::{c_char, c_double, c_int};
             use types::os::arch::c95::{c_long, c_uint, c_ulong};
-            use types::os::arch::c95::{size_t};
+            use types::os::arch::c95::size_t;
 
             extern {
                 pub fn abs(i: c_int) -> c_int;
@@ -5501,12 +6153,9 @@ pub mod funcs {
                 // Omitted: div, ldiv (return pub type incomplete).
                 pub fn atof(s: *const c_char) -> c_double;
                 pub fn atoi(s: *const c_char) -> c_int;
-                pub fn strtod(s: *const c_char,
-                              endp: *mut *mut c_char) -> c_double;
-                pub fn strtol(s: *const c_char,
-                              endp: *mut *mut c_char, base: c_int) -> c_long;
-                pub fn strtoul(s: *const c_char, endp: *mut *mut c_char,
-                               base: c_int) -> c_ulong;
+                pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double;
+                pub fn strtol(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_long;
+                pub fn strtoul(s: *const c_char, endp: *mut *mut c_char, base: c_int) -> c_ulong;
                 pub fn calloc(nobj: size_t, size: size_t) -> *mut c_void;
                 pub fn malloc(size: size_t) -> *mut c_void;
                 pub fn realloc(p: *mut c_void, size: size_t) -> *mut c_void;
@@ -5514,7 +6163,7 @@ pub mod funcs {
 
                 /// Exits the running program in a possibly dangerous manner.
                 ///
-                /// # Unsafety
+                /// # Safety
                 ///
                 /// While this forces your program to exit, it does so in a way that has
                 /// consequences. This will skip all unwinding code, which means that anything
@@ -5534,7 +6183,7 @@ pub mod funcs {
                 /// ```
                 pub fn exit(status: c_int) -> !;
                 pub fn _exit(status: c_int) -> !;
-                pub fn atexit(cb: extern fn()) -> c_int;
+                pub fn atexit(cb: extern "C" fn()) -> c_int;
                 pub fn system(s: *const c_char) -> c_int;
                 pub fn getenv(s: *const c_char) -> *mut c_char;
                 // Omitted: bsearch, qsort
@@ -5546,43 +6195,34 @@ pub mod funcs {
         pub mod string {
             use types::common::c95::c_void;
             use types::os::arch::c95::{c_char, c_int, size_t};
-            use types::os::arch::c95::{wchar_t};
+            use types::os::arch::c95::wchar_t;
 
             extern {
-                pub fn strcpy(dst: *mut c_char,
-                              src: *const c_char) -> *mut c_char;
-                pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t)
-                               -> *mut c_char;
+                pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char;
+                pub fn strncpy(dst: *mut c_char, src: *const c_char, n: size_t) -> *mut c_char;
                 pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char;
-                pub fn strncat(s: *mut c_char, ct: *const c_char,
-                               n: size_t) -> *mut c_char;
+                pub fn strncat(s: *mut c_char, ct: *const c_char, n: size_t) -> *mut c_char;
                 pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int;
-                pub fn strncmp(cs: *const c_char, ct: *const c_char,
-                               n: size_t) -> c_int;
+                pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int;
                 pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int;
                 pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char;
                 pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char;
                 pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t;
                 pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t;
-                pub fn strpbrk(cs: *const c_char,
-                               ct: *const c_char) -> *mut c_char;
-                pub fn strstr(cs: *const c_char,
-                              ct: *const c_char) -> *mut c_char;
+                pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char;
+                pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char;
                 pub fn strlen(cs: *const c_char) -> size_t;
                 pub fn strerror(n: c_int) -> *mut c_char;
                 pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char;
-                pub fn strxfrm(s: *mut c_char, ct: *const c_char,
-                               n: size_t) -> size_t;
+                pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t;
                 pub fn wcslen(buf: *const wchar_t) -> size_t;
 
                 // Omitted: memcpy, memmove, memset (provided by LLVM)
 
                 // These are fine to execute on the Rust stack. They must be,
                 // in fact, because LLVM generates calls to them!
-                pub fn memcmp(cx: *const c_void, ct: *const c_void,
-                              n: size_t) -> c_int;
-                pub fn memchr(cx: *const c_void, c: c_int,
-                              n: size_t) -> *mut c_void;
+                pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int;
+                pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void;
             }
         }
     }
@@ -5625,8 +6265,7 @@ pub mod funcs {
 
             extern {
                 #[link_name = "_popen"]
-                pub fn popen(command: *const c_char,
-                             mode: *const c_char) -> *mut FILE;
+                pub fn popen(command: *const c_char, mode: *const c_char) -> *mut FILE;
                 #[link_name = "_pclose"]
                 pub fn pclose(stream: *mut FILE) -> c_int;
                 #[link_name = "_fdopen"]
@@ -5640,11 +6279,9 @@ pub mod funcs {
             use types::os::arch::c95::{c_int, c_char, wchar_t};
             extern {
                 #[link_name = "_open"]
-                pub fn open(path: *const c_char, oflag: c_int, mode: c_int)
-                            -> c_int;
+                pub fn open(path: *const c_char, oflag: c_int, mode: c_int) -> c_int;
                 #[link_name = "_wopen"]
-                pub fn wopen(path: *const wchar_t, oflag: c_int, mode: c_int)
-                            -> c_int;
+                pub fn wopen(path: *const wchar_t, oflag: c_int, mode: c_int) -> c_int;
                 #[link_name = "_creat"]
                 pub fn creat(path: *const c_char, mode: c_int) -> c_int;
             }
@@ -5656,8 +6293,7 @@ pub mod funcs {
 
         pub mod unistd {
             use types::common::c95::c_void;
-            use types::os::arch::c95::{c_int, c_uint, c_char,
-                                             c_long, size_t};
+            use types::os::arch::c95::{c_int, c_uint, c_char, c_long, size_t};
             use types::os::arch::c99::intptr_t;
 
             extern {
@@ -5672,18 +6308,19 @@ pub mod funcs {
                 #[link_name = "_dup2"]
                 pub fn dup2(src: c_int, dst: c_int) -> c_int;
                 #[link_name = "_execv"]
-                pub fn execv(prog: *const c_char,
-                             argv: *const *const c_char) -> intptr_t;
+                pub fn execv(prog: *const c_char, argv: *const *const c_char) -> intptr_t;
                 #[link_name = "_execve"]
-                pub fn execve(prog: *const c_char, argv: *const *const c_char,
+                pub fn execve(prog: *const c_char,
+                              argv: *const *const c_char,
                               envp: *const *const c_char)
                               -> c_int;
                 #[link_name = "_execvp"]
-                pub fn execvp(c: *const c_char,
-                              argv: *const *const c_char) -> c_int;
+                pub fn execvp(c: *const c_char, argv: *const *const c_char) -> c_int;
                 #[link_name = "_execvpe"]
-                pub fn execvpe(c: *const c_char, argv: *const *const c_char,
-                               envp: *const *const c_char) -> c_int;
+                pub fn execvpe(c: *const c_char,
+                               argv: *const *const c_char,
+                               envp: *const *const c_char)
+                               -> c_int;
                 #[link_name = "_getcwd"]
                 pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char;
                 #[link_name = "_getpid"]
@@ -5691,21 +6328,17 @@ pub mod funcs {
                 #[link_name = "_isatty"]
                 pub fn isatty(fd: c_int) -> c_int;
                 #[link_name = "_lseek"]
-                pub fn lseek(fd: c_int, offset: c_long, origin: c_int)
-                             -> c_long;
+                pub fn lseek(fd: c_int, offset: c_long, origin: c_int) -> c_long;
                 #[link_name = "_pipe"]
-                pub fn pipe(fds: *mut c_int, psize: c_uint, textmode: c_int)
-                            -> c_int;
+                pub fn pipe(fds: *mut c_int, psize: c_uint, textmode: c_int) -> c_int;
                 #[link_name = "_read"]
-                pub fn read(fd: c_int, buf: *mut c_void, count: c_uint)
-                            -> c_int;
+                pub fn read(fd: c_int, buf: *mut c_void, count: c_uint) -> c_int;
                 #[link_name = "_rmdir"]
                 pub fn rmdir(path: *const c_char) -> c_int;
                 #[link_name = "_unlink"]
                 pub fn unlink(c: *const c_char) -> c_int;
                 #[link_name = "_write"]
-                pub fn write(fd: c_int, buf: *const c_void,
-                             count: c_uint) -> c_int;
+                pub fn write(fd: c_int, buf: *const c_void, count: c_uint) -> c_int;
             }
         }
 
@@ -5733,38 +6366,16 @@ pub mod funcs {
                 pub fn chmod(path: *const c_char, mode: mode_t) -> c_int;
                 pub fn fchmod(fd: c_int, mode: mode_t) -> c_int;
 
-                #[cfg(any(target_os = "linux",
-                          target_os = "freebsd",
-                          target_os = "dragonfly",
-                          target_os = "bitrig",
-                          target_os = "netbsd",
-                          target_os = "openbsd",
-                          target_os = "android",
-                          target_os = "ios",
-                          target_os = "nacl"))]
-                pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
-
-                #[cfg(target_os = "macos")]
-                #[link_name = "fstat64"]
+                #[cfg_attr(target_os = "macos", link_name = "fstat64")]
+                #[cfg_attr(target_os = "netbsd", link_name = "__fstat50")]
                 pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
 
                 pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int;
                 #[cfg(not(target_os = "nacl"))]
                 pub fn mkfifo(path: *const c_char, mode: mode_t) -> c_int;
 
-                #[cfg(any(target_os = "linux",
-                          target_os = "freebsd",
-                          target_os = "dragonfly",
-                          target_os = "bitrig",
-                          target_os = "netbsd",
-                          target_os = "openbsd",
-                          target_os = "android",
-                          target_os = "ios",
-                          target_os = "nacl"))]
-                pub fn stat(path: *const c_char, buf: *mut stat) -> c_int;
-
-                #[cfg(target_os = "macos")]
-                #[link_name = "stat64"]
+                #[cfg_attr(target_os = "macos", link_name = "stat64")]
+                #[cfg_attr(target_os = "netbsd", link_name = "__stat50")]
                 pub fn stat(path: *const c_char, buf: *mut stat) -> c_int;
             }
         }
@@ -5774,8 +6385,7 @@ pub mod funcs {
             use types::os::arch::c95::{c_char, c_int};
 
             extern {
-                pub fn popen(command: *const c_char,
-                             mode: *const c_char) -> *mut FILE;
+                pub fn popen(command: *const c_char, mode: *const c_char) -> *mut FILE;
                 pub fn pclose(stream: *mut FILE) -> c_int;
                 pub fn fdopen(fd: c_int, mode: *const c_char) -> *mut FILE;
                 pub fn fileno(stream: *mut FILE) -> c_int;
@@ -5790,20 +6400,21 @@ pub mod funcs {
                 extern {
                     #[cfg(any(target_os = "macos",
                               target_os = "ios"))]
-                    pub fn open(path: *const ::c_char, oflag: ::c_int, ...)
-                                -> ::c_int;
+                    pub fn open(path: *const ::c_char, oflag: ::c_int, ...) -> ::c_int;
 
                     #[cfg(not(any(target_os = "macos",
                                   target_os = "ios")))]
-                    pub fn open(path: *const ::c_char, oflag: ::c_int, mode: ::mode_t)
-                                -> ::c_int;
+                    pub fn open(path: *const ::c_char, oflag: ::c_int, mode: ::mode_t) -> ::c_int;
                 }
             }
 
             #[cfg(any(target_os = "macos",
                       target_os = "ios"))]
             #[inline]
-            pub unsafe extern fn open(path: *const c_char, oflag: c_int, mode: mode_t) -> c_int {
+            pub unsafe extern "C" fn open(path: *const c_char,
+                                          oflag: c_int,
+                                          mode: mode_t)
+                                          -> c_int {
                 use types::os::arch::c95::c_uint;
                 open_shim::open(path, oflag, mode as c_uint)
             }
@@ -5811,7 +6422,10 @@ pub mod funcs {
             #[cfg(not(any(target_os = "macos",
                           target_os = "ios")))]
             #[inline]
-            pub unsafe extern fn open(path: *const c_char, oflag: c_int, mode: mode_t) -> c_int {
+            pub unsafe extern "C" fn open(path: *const c_char,
+                                          oflag: c_int,
+                                          mode: mode_t)
+                                          -> c_int {
                 open_shim::open(path, oflag, mode)
             }
 
@@ -5836,8 +6450,10 @@ pub mod funcs {
                 #[link_name="rust_opendir"]
                 pub fn opendir(dirname: *const c_char) -> *mut DIR;
                 #[link_name="rust_readdir_r"]
-                pub fn readdir_r(dirp: *mut DIR, entry: *mut dirent_t,
-                                  result: *mut *mut dirent_t) -> c_int;
+                pub fn readdir_r(dirp: *mut DIR,
+                                 entry: *mut dirent_t,
+                                 result: *mut *mut dirent_t)
+                                 -> c_int;
             }
 
             extern {
@@ -5851,7 +6467,7 @@ pub mod funcs {
         pub mod unistd {
             use types::common::c95::c_void;
             use types::os::arch::c95::{c_char, c_int, c_long, c_uint};
-            use types::os::arch::c95::{size_t};
+            use types::os::arch::c95::size_t;
             use types::os::common::posix01::timespec;
             use types::os::arch::posix01::utimbuf;
             use types::os::arch::posix88::{gid_t, off_t, pid_t};
@@ -5862,31 +6478,27 @@ pub mod funcs {
                 pub fn access(path: *const c_char, amode: c_int) -> c_int;
                 pub fn alarm(seconds: c_uint) -> c_uint;
                 pub fn chdir(dir: *const c_char) -> c_int;
-                pub fn chown(path: *const c_char, uid: uid_t,
-                             gid: gid_t) -> c_int;
+                pub fn chown(path: *const c_char, uid: uid_t, gid: gid_t) -> c_int;
                 pub fn close(fd: c_int) -> c_int;
                 pub fn dup(fd: c_int) -> c_int;
                 pub fn dup2(src: c_int, dst: c_int) -> c_int;
-                pub fn execv(prog: *const c_char,
-                             argv: *const *const c_char) -> c_int;
-                pub fn execve(prog: *const c_char, argv: *const *const c_char,
+                pub fn execv(prog: *const c_char, argv: *const *const c_char) -> c_int;
+                pub fn execve(prog: *const c_char,
+                              argv: *const *const c_char,
                               envp: *const *const c_char)
                               -> c_int;
-                pub fn execvp(c: *const c_char,
-                              argv: *const *const c_char) -> c_int;
+                pub fn execvp(c: *const c_char, argv: *const *const c_char) -> c_int;
                 pub fn fork() -> pid_t;
                 pub fn fpathconf(filedes: c_int, name: c_int) -> c_long;
                 pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char;
                 pub fn getegid() -> gid_t;
                 pub fn geteuid() -> uid_t;
                 pub fn getgid() -> gid_t;
-                pub fn getgroups(ngroups_max: c_int, groups: *mut gid_t)
-                                 -> c_int;
+                pub fn getgroups(ngroups_max: c_int, groups: *mut gid_t) -> c_int;
                 pub fn getlogin() -> *mut c_char;
                 // GNU getopt(3) modifies its arguments despite the
                 // char * const [] prototype; see the manpage.
-                pub fn getopt(argc: c_int, argv: *mut *mut c_char,
-                              optstr: *const c_char) -> c_int;
+                pub fn getopt(argc: c_int, argv: *mut *mut c_char, optstr: *const c_char) -> c_int;
                 pub fn getpgrp() -> pid_t;
                 pub fn getpid() -> pid_t;
                 pub fn getppid() -> pid_t;
@@ -5894,13 +6506,11 @@ pub mod funcs {
                 pub fn getsid(pid: pid_t) -> pid_t;
                 pub fn isatty(fd: c_int) -> c_int;
                 pub fn link(src: *const c_char, dst: *const c_char) -> c_int;
-                pub fn lseek(fd: c_int, offset: off_t, whence: c_int)
-                             -> off_t;
+                pub fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t;
                 pub fn pathconf(path: *mut c_char, name: c_int) -> c_long;
                 pub fn pause() -> c_int;
                 pub fn pipe(fds: *mut c_int) -> c_int;
-                pub fn read(fd: c_int, buf: *mut c_void, count: size_t)
-                            -> ssize_t;
+                pub fn read(fd: c_int, buf: *mut c_void, count: size_t) -> ssize_t;
                 pub fn rmdir(path: *const c_char) -> c_int;
                 pub fn setgid(gid: gid_t) -> c_int;
                 pub fn setpgid(pid: pid_t, pgid: pid_t) -> c_int;
@@ -5908,82 +6518,80 @@ pub mod funcs {
                 pub fn setuid(uid: uid_t) -> c_int;
                 pub fn sleep(secs: c_uint) -> c_uint;
                 pub fn usleep(secs: c_uint) -> c_int;
-                pub fn nanosleep(rqtp: *const timespec,
-                                 rmtp: *mut timespec) -> c_int;
+                #[cfg_attr(target_os = "netbsd", link_name = "__nanosleep50")]
+                pub fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int;
                 pub fn sysconf(name: c_int) -> c_long;
                 pub fn tcgetpgrp(fd: c_int) -> pid_t;
                 pub fn ttyname(fd: c_int) -> *mut c_char;
                 pub fn unlink(c: *const c_char) -> c_int;
                 pub fn wait(status: *const c_int) -> pid_t;
-                pub fn waitpid(pid: pid_t, status: *const c_int, options: c_int)
-                               -> pid_t;
-                pub fn write(fd: c_int, buf: *const c_void, count: size_t)
-                             -> ssize_t;
-                pub fn pread(fd: c_int, buf: *mut c_void, count: size_t,
-                             offset: off_t) -> ssize_t;
-                pub fn pwrite(fd: c_int, buf: *const c_void, count: size_t,
-                              offset: off_t) -> ssize_t;
+                pub fn waitpid(pid: pid_t, status: *const c_int, options: c_int) -> pid_t;
+                pub fn write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t;
+                pub fn pread(fd: c_int, buf: *mut c_void, count: size_t, offset: off_t) -> ssize_t;
+                pub fn pwrite(fd: c_int,
+                              buf: *const c_void,
+                              count: size_t,
+                              offset: off_t)
+                              -> ssize_t;
+                #[cfg_attr(target_os = "netbsd", link_name = "__utime50")]
                 pub fn utime(file: *const c_char, buf: *const utimbuf) -> c_int;
             }
             #[cfg(target_os = "nacl")]
             extern {
                 pub fn access(path: *const c_char, amode: c_int) -> c_int;
                 pub fn chdir(dir: *const c_char) -> c_int;
-                pub fn chown(path: *const c_char, uid: uid_t,
-                             gid: gid_t) -> c_int;
+                pub fn chown(path: *const c_char, uid: uid_t, gid: gid_t) -> c_int;
                 pub fn close(fd: c_int) -> c_int;
                 pub fn dup(fd: c_int) -> c_int;
                 pub fn dup2(src: c_int, dst: c_int) -> c_int;
-                pub fn execv(prog: *const c_char,
-                             argv: *const *const c_char) -> c_int;
-                pub fn execve(prog: *const c_char, argv: *const *const c_char,
+                pub fn execv(prog: *const c_char, argv: *const *const c_char) -> c_int;
+                pub fn execve(prog: *const c_char,
+                              argv: *const *const c_char,
                               envp: *const *const c_char)
                               -> c_int;
-                pub fn execvp(c: *const c_char,
-                              argv: *const *const c_char) -> c_int;
+                pub fn execvp(c: *const c_char, argv: *const *const c_char) -> c_int;
                 pub fn fork() -> pid_t;
                 pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char;
                 pub fn getegid() -> gid_t;
                 pub fn geteuid() -> uid_t;
                 pub fn getgid() -> gid_t;
                 pub fn getlogin() -> *mut c_char;
-                pub fn getopt(argc: c_int, argv: *const *const c_char,
-                              optstr: *const c_char) -> c_int;
+                pub fn getopt(argc: c_int,
+                              argv: *const *const c_char,
+                              optstr: *const c_char)
+                              -> c_int;
                 pub fn getuid() -> uid_t;
                 pub fn getsid(pid: pid_t) -> pid_t;
                 pub fn isatty(fd: c_int) -> c_int;
                 pub fn link(src: *const c_char, dst: *const c_char) -> c_int;
-                pub fn lseek(fd: c_int, offset: off_t, whence: c_int)
-                             -> off_t;
+                pub fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t;
                 pub fn pipe(fds: *mut c_int) -> c_int;
-                pub fn read(fd: c_int, buf: *mut c_void, count: size_t)
-                            -> ssize_t;
+                pub fn read(fd: c_int, buf: *mut c_void, count: size_t) -> ssize_t;
                 pub fn rmdir(path: *const c_char) -> c_int;
                 pub fn setgid(gid: gid_t) -> c_int;
                 pub fn setuid(uid: uid_t) -> c_int;
                 pub fn sleep(secs: c_uint) -> c_uint;
                 pub fn usleep(secs: c_uint) -> c_int;
-                pub fn nanosleep(rqtp: *const timespec,
-                                 rmtp: *mut timespec) -> c_int;
+                pub fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int;
                 pub fn sysconf(name: c_int) -> c_long;
                 pub fn ttyname(fd: c_int) -> *mut c_char;
                 pub fn unlink(c: *const c_char) -> c_int;
                 pub fn wait(status: *const c_int) -> pid_t;
-                pub fn waitpid(pid: pid_t, status: *const c_int, options: c_int)
-                               -> pid_t;
-                pub fn write(fd: c_int, buf: *const c_void, count: size_t)
-                             -> ssize_t;
-                pub fn pread(fd: c_int, buf: *mut c_void, count: size_t,
-                             offset: off_t) -> ssize_t;
-                pub fn pwrite(fd: c_int, buf: *const c_void, count: size_t,
-                              offset: off_t) -> ssize_t;
+                pub fn waitpid(pid: pid_t, status: *const c_int, options: c_int) -> pid_t;
+                pub fn write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t;
+                pub fn pread(fd: c_int, buf: *mut c_void, count: size_t, offset: off_t) -> ssize_t;
+                pub fn pwrite(fd: c_int,
+                              buf: *const c_void,
+                              count: size_t,
+                              offset: off_t)
+                              -> ssize_t;
                 pub fn utime(file: *const c_char, buf: *const utimbuf) -> c_int;
             }
         }
 
         pub mod signal {
-            use types::os::arch::c95::{c_int};
-            use types::os::arch::posix88::{pid_t};
+            use types::os::arch::c95::c_int;
+            use types::os::arch::posix88::pid_t;
 
             extern {
                 pub fn kill(pid: pid_t, sig: c_int) -> c_int;
@@ -5991,7 +6599,7 @@ pub mod funcs {
         }
 
         pub mod mman {
-            use types::common::c95::{c_void};
+            use types::common::c95::c_void;
             use types::os::arch::c95::{size_t, c_int, c_char};
             use types::os::arch::posix88::{mode_t, off_t};
 
@@ -6002,13 +6610,12 @@ pub mod funcs {
                 pub fn mlockall(flags: c_int) -> c_int;
                 pub fn munlockall() -> c_int;
 
-                pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int)
-                                -> c_int;
+                pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int) -> c_int;
 
-                pub fn msync(addr: *mut c_void, len: size_t, flags: c_int)
-                             -> c_int;
-                pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t)
-                                -> c_int;
+                #[cfg_attr(target_os = "netbsd", link_name = "__msync13")]
+                pub fn msync(addr: *mut c_void, len: size_t, flags: c_int) -> c_int;
+
+                pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t) -> c_int;
                 pub fn shm_unlink(name: *const c_char) -> c_int;
             }
 
@@ -6051,19 +6658,8 @@ pub mod funcs {
             use types::os::arch::posix01::stat;
 
             extern {
-                #[cfg(any(target_os = "linux",
-                          target_os = "freebsd",
-                          target_os = "dragonfly",
-                          target_os = "bitrig",
-                          target_os = "netbsd",
-                          target_os = "openbsd",
-                          target_os = "android",
-                          target_os = "ios",
-                          target_os = "nacl"))]
-                pub fn lstat(path: *const c_char, buf: *mut stat) -> c_int;
-
-                #[cfg(target_os = "macos")]
-                #[link_name = "lstat64"]
+                #[cfg_attr(target_os = "macos", link_name = "lstat64")]
+                #[cfg_attr(target_os = "netbsd", link_name = "__lstat50")]
                 pub fn lstat(path: *const c_char, buf: *mut stat) -> c_int;
             }
         }
@@ -6073,23 +6669,20 @@ pub mod funcs {
             use types::os::arch::posix88::{ssize_t, off_t};
 
             extern {
-                pub fn readlink(path: *const c_char,
-                                buf: *mut c_char,
-                                bufsz: size_t)
-                                -> ssize_t;
+                pub fn readlink(path: *const c_char, buf: *mut c_char, bufsz: size_t) -> ssize_t;
 
                 pub fn fsync(fd: c_int) -> c_int;
 
                 #[cfg(any(target_os = "linux", target_os = "android"))]
                 pub fn fdatasync(fd: c_int) -> c_int;
 
-                pub fn setenv(name: *const c_char, val: *const c_char,
-                              overwrite: c_int) -> c_int;
+                pub fn setenv(name: *const c_char, val: *const c_char, overwrite: c_int) -> c_int;
+                #[cfg_attr(target_os = "netbsd", link_name = "__unsetenv13")]
                 pub fn unsetenv(name: *const c_char) -> c_int;
+                #[cfg_attr(target_os = "netbsd", link_name = "__putenv50")]
                 pub fn putenv(string: *mut c_char) -> c_int;
 
-                pub fn symlink(path1: *const c_char,
-                               path2: *const c_char) -> c_int;
+                pub fn symlink(path1: *const c_char, path2: *const c_char) -> c_int;
 
                 pub fn ftruncate(fd: c_int, length: off_t) -> c_int;
             }
@@ -6102,43 +6695,40 @@ pub mod funcs {
             #[cfg(not(all(target_os = "android", any(target_arch = "arm",
                                                      target_arch = "x86"))))]
             extern {
-                pub fn signal(signum: c_int,
-                              handler: sighandler_t) -> sighandler_t;
+                pub fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t;
             }
 
             #[cfg(all(target_os = "android", any(target_arch = "arm",
                                                  target_arch = "x86")))]
             extern {
                 #[link_name = "bsd_signal"]
-                pub fn signal(signum: c_int,
-                              handler: sighandler_t) -> sighandler_t;
+                pub fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t;
             }
         }
 
         pub mod glob {
             use types::os::arch::c95::{c_char, c_int};
-            use types::os::common::posix01::{glob_t};
+            use types::os::common::posix01::glob_t;
 
             extern {
+                #[cfg_attr(target_os = "netbsd", link_name = "__glob30")]
                 pub fn glob(pattern: *const c_char,
                             flags: c_int,
                             errfunc: ::core::option::Option<extern "C" fn(epath: *const c_char,
                                                               errno: c_int) -> c_int>,
                             pglob: *mut glob_t);
+                #[cfg_attr(target_os = "netbsd", link_name = "__globfree30")]
                 pub fn globfree(pglob: *mut glob_t);
             }
         }
 
         pub mod mman {
-            use types::common::c95::{c_void};
+            use types::common::c95::c_void;
             use types::os::arch::c95::{c_int, size_t};
 
             #[cfg(not(target_os = "nacl"))]
             extern {
-                pub fn posix_madvise(addr: *mut c_void,
-                                     len: size_t,
-                                     advice: c_int)
-                                     -> c_int;
+                pub fn posix_madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int;
             }
         }
 
@@ -6149,8 +6739,8 @@ pub mod funcs {
             extern {
                 pub fn getrlimit(resource: c_int, rlim: *mut rlimit) -> c_int;
                 pub fn setrlimit(resource: c_int, rlim: *const rlimit) -> c_int;
+                #[cfg_attr(target_os = "netbsd", link_name = "__getrusage50")]
                 pub fn getrusage(resource: c_int, usage: *mut rusage) -> c_int;
-
             }
         }
     }
@@ -6192,37 +6782,52 @@ pub mod funcs {
 
     #[cfg(not(windows))]
     pub mod bsd43 {
-        use types::common::c95::{c_void};
+        use types::common::c95::c_void;
         use types::os::common::bsd44::{socklen_t, sockaddr, ifaddrs};
         use types::os::arch::c95::{c_int, size_t};
         use types::os::arch::posix88::ssize_t;
 
         extern "system" {
+            #[cfg_attr(target_os = "netbsd", link_name = "__socket30")]
             pub fn socket(domain: c_int, ty: c_int, protocol: c_int) -> c_int;
-            pub fn connect(socket: c_int, address: *const sockaddr,
-                           len: socklen_t) -> c_int;
-            pub fn bind(socket: c_int, address: *const sockaddr,
-                        address_len: socklen_t) -> c_int;
+
+            pub fn connect(socket: c_int, address: *const sockaddr, len: socklen_t) -> c_int;
+            pub fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int;
             pub fn listen(socket: c_int, backlog: c_int) -> c_int;
-            pub fn accept(socket: c_int, address: *mut sockaddr,
-                          address_len: *mut socklen_t) -> c_int;
-            pub fn getpeername(socket: c_int, address: *mut sockaddr,
-                               address_len: *mut socklen_t) -> c_int;
-            pub fn getsockname(socket: c_int, address: *mut sockaddr,
-                               address_len: *mut socklen_t) -> c_int;
-            pub fn setsockopt(socket: c_int, level: c_int, name: c_int,
+            pub fn accept(socket: c_int,
+                          address: *mut sockaddr,
+                          address_len: *mut socklen_t)
+                          -> c_int;
+            pub fn getpeername(socket: c_int,
+                               address: *mut sockaddr,
+                               address_len: *mut socklen_t)
+                               -> c_int;
+            pub fn getsockname(socket: c_int,
+                               address: *mut sockaddr,
+                               address_len: *mut socklen_t)
+                               -> c_int;
+            pub fn setsockopt(socket: c_int,
+                              level: c_int,
+                              name: c_int,
                               value: *const c_void,
-                              option_len: socklen_t) -> c_int;
-            pub fn recv(socket: c_int, buf: *mut c_void, len: size_t,
-                        flags: c_int) -> ssize_t;
-            pub fn send(socket: c_int, buf: *const c_void, len: size_t,
-                        flags: c_int) -> ssize_t;
-            pub fn recvfrom(socket: c_int, buf: *mut c_void, len: size_t,
-                            flags: c_int, addr: *mut sockaddr,
-                            addrlen: *mut socklen_t) -> ssize_t;
-            pub fn sendto(socket: c_int, buf: *const c_void, len: size_t,
-                          flags: c_int, addr: *const sockaddr,
-                          addrlen: socklen_t) -> ssize_t;
+                              option_len: socklen_t)
+                              -> c_int;
+            pub fn recv(socket: c_int, buf: *mut c_void, len: size_t, flags: c_int) -> ssize_t;
+            pub fn send(socket: c_int, buf: *const c_void, len: size_t, flags: c_int) -> ssize_t;
+            pub fn recvfrom(socket: c_int,
+                            buf: *mut c_void,
+                            len: size_t,
+                            flags: c_int,
+                            addr: *mut sockaddr,
+                            addrlen: *mut socklen_t)
+                            -> ssize_t;
+            pub fn sendto(socket: c_int,
+                          buf: *const c_void,
+                          len: size_t,
+                          flags: c_int,
+                          addr: *const sockaddr,
+                          addrlen: socklen_t)
+                          -> ssize_t;
             pub fn getifaddrs(ifap: *mut *mut ifaddrs) -> c_int;
             pub fn freeifaddrs(ifa: *mut ifaddrs);
             pub fn shutdown(socket: c_int, how: c_int) -> c_int;
@@ -6231,37 +6836,50 @@ pub mod funcs {
 
     #[cfg(windows)]
     pub mod bsd43 {
-        use types::common::c95::{c_void};
+        use types::common::c95::c_void;
         use types::os::common::bsd44::{socklen_t, sockaddr, SOCKET};
         use types::os::arch::c95::c_int;
 
         extern "system" {
             pub fn socket(domain: c_int, ty: c_int, protocol: c_int) -> SOCKET;
-            pub fn connect(socket: SOCKET, address: *const sockaddr,
-                           len: socklen_t) -> c_int;
-            pub fn bind(socket: SOCKET, address: *const sockaddr,
-                        address_len: socklen_t) -> c_int;
+            pub fn connect(socket: SOCKET, address: *const sockaddr, len: socklen_t) -> c_int;
+            pub fn bind(socket: SOCKET, address: *const sockaddr, address_len: socklen_t) -> c_int;
             pub fn listen(socket: SOCKET, backlog: c_int) -> c_int;
-            pub fn accept(socket: SOCKET, address: *mut sockaddr,
-                          address_len: *mut socklen_t) -> SOCKET;
-            pub fn getpeername(socket: SOCKET, address: *mut sockaddr,
-                               address_len: *mut socklen_t) -> c_int;
-            pub fn getsockname(socket: SOCKET, address: *mut sockaddr,
-                               address_len: *mut socklen_t) -> c_int;
-            pub fn setsockopt(socket: SOCKET, level: c_int, name: c_int,
+            pub fn accept(socket: SOCKET,
+                          address: *mut sockaddr,
+                          address_len: *mut socklen_t)
+                          -> SOCKET;
+            pub fn getpeername(socket: SOCKET,
+                               address: *mut sockaddr,
+                               address_len: *mut socklen_t)
+                               -> c_int;
+            pub fn getsockname(socket: SOCKET,
+                               address: *mut sockaddr,
+                               address_len: *mut socklen_t)
+                               -> c_int;
+            pub fn setsockopt(socket: SOCKET,
+                              level: c_int,
+                              name: c_int,
                               value: *const c_void,
-                              option_len: socklen_t) -> c_int;
+                              option_len: socklen_t)
+                              -> c_int;
             pub fn closesocket(socket: SOCKET) -> c_int;
-            pub fn recv(socket: SOCKET, buf: *mut c_void, len: c_int,
-                        flags: c_int) -> c_int;
-            pub fn send(socket: SOCKET, buf: *const c_void, len: c_int,
-                        flags: c_int) -> c_int;
-            pub fn recvfrom(socket: SOCKET, buf: *mut c_void, len: c_int,
-                            flags: c_int, addr: *mut sockaddr,
-                            addrlen: *mut c_int) -> c_int;
-            pub fn sendto(socket: SOCKET, buf: *const c_void, len: c_int,
-                          flags: c_int, addr: *const sockaddr,
-                          addrlen: c_int) -> c_int;
+            pub fn recv(socket: SOCKET, buf: *mut c_void, len: c_int, flags: c_int) -> c_int;
+            pub fn send(socket: SOCKET, buf: *const c_void, len: c_int, flags: c_int) -> c_int;
+            pub fn recvfrom(socket: SOCKET,
+                            buf: *mut c_void,
+                            len: c_int,
+                            flags: c_int,
+                            addr: *mut sockaddr,
+                            addrlen: *mut c_int)
+                            -> c_int;
+            pub fn sendto(socket: SOCKET,
+                          buf: *const c_void,
+                          len: c_int,
+                          flags: c_int,
+                          addr: *const sockaddr,
+                          addrlen: c_int)
+                          -> c_int;
             pub fn shutdown(socket: SOCKET, how: c_int) -> c_int;
         }
     }
@@ -6274,7 +6892,7 @@ pub mod funcs {
               target_os = "netbsd",
               target_os = "openbsd"))]
     pub mod bsd44 {
-        use types::common::c95::{c_void};
+        use types::common::c95::c_void;
         use types::os::arch::c95::{c_char, c_uchar, c_int, c_uint, c_ulong, size_t};
 
         extern {
@@ -6297,19 +6915,16 @@ pub mod funcs {
                                    sizep: *mut size_t)
                                    -> c_int;
             pub fn getdtablesize() -> c_int;
-            pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int)
-                           -> c_int;
-            pub fn mincore(addr: *mut c_void, len: size_t, vec: *mut c_uchar)
-                           -> c_int;
-            pub fn realpath(pathname: *const c_char, resolved: *mut c_char)
-                            -> *mut c_char;
+            pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int;
+            pub fn mincore(addr: *mut c_void, len: size_t, vec: *mut c_uchar) -> c_int;
+            pub fn realpath(pathname: *const c_char, resolved: *mut c_char) -> *mut c_char;
             pub fn flock(fd: c_int, operation: c_int) -> c_int;
         }
     }
 
     #[cfg(any(target_os = "linux", target_os = "android"))]
     pub mod bsd44 {
-        use types::common::c95::{c_void};
+        use types::common::c95::c_void;
         use types::os::arch::c95::{c_uchar, c_int, size_t};
         #[cfg(not(feature = "cargo-build"))]
         use types::os::arch::c95::c_ulong;
@@ -6327,10 +6942,8 @@ pub mod funcs {
             pub fn ioctl(fd: c_int, request: c_int, ...) -> c_int;
             #[cfg(not(feature = "cargo-build"))]
             pub fn ioctl(fd: c_int, request: c_ulong, ...) -> c_int;
-            pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int)
-                           -> c_int;
-            pub fn mincore(addr: *mut c_void, len: size_t, vec: *mut c_uchar)
-                           -> c_int;
+            pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int) -> c_int;
+            pub fn mincore(addr: *mut c_void, len: size_t, vec: *mut c_uchar) -> c_int;
             pub fn flock(fd: c_int, operation: c_int) -> c_int;
         }
     }
@@ -6352,8 +6965,7 @@ pub mod funcs {
         use types::os::arch::c95::{c_char, c_int};
 
         extern {
-            pub fn _NSGetExecutablePath(buf: *mut c_char, bufsize: *mut u32)
-                                        -> c_int;
+            pub fn _NSGetExecutablePath(buf: *mut c_char, bufsize: *mut u32) -> c_int;
         }
     }
 
@@ -6374,26 +6986,17 @@ pub mod funcs {
     pub mod extra {
 
         pub mod kernel32 {
-            use types::os::arch::c95::{c_uint};
-            use types::os::arch::extra::{BOOL, DWORD, SIZE_T, HMODULE,
-                                               LPCWSTR, LPWSTR,
-                                               LPWCH, LPDWORD, LPVOID,
-                                               LPCVOID, LPOVERLAPPED,
-                                               LPSECURITY_ATTRIBUTES,
-                                               LPSTARTUPINFO,
-                                               LPPROCESS_INFORMATION,
-                                               LPMEMORY_BASIC_INFORMATION,
-                                               LPSYSTEM_INFO, HANDLE, LPHANDLE,
-                                               LARGE_INTEGER, PLARGE_INTEGER,
-                                               LPFILETIME, LPWIN32_FIND_DATAW};
+            use types::os::arch::c95::c_uint;
+            use types::os::arch::extra::{BOOL, DWORD, SIZE_T, HMODULE, LPCWSTR, LPWSTR, LPWCH,
+                                         LPDWORD, LPVOID, LPCVOID, LPOVERLAPPED,
+                                         LPSECURITY_ATTRIBUTES, LPSTARTUPINFO,
+                                         LPPROCESS_INFORMATION, LPMEMORY_BASIC_INFORMATION,
+                                         LPSYSTEM_INFO, HANDLE, LPHANDLE, LARGE_INTEGER,
+                                         PLARGE_INTEGER, LPFILETIME, LPWIN32_FIND_DATAW};
 
             extern "system" {
-                pub fn GetEnvironmentVariableW(n: LPCWSTR,
-                                               v: LPWSTR,
-                                               nsize: DWORD)
-                                               -> DWORD;
-                pub fn SetEnvironmentVariableW(n: LPCWSTR, v: LPCWSTR)
-                                               -> BOOL;
+                pub fn GetEnvironmentVariableW(n: LPCWSTR, v: LPWSTR, nsize: DWORD) -> DWORD;
+                pub fn SetEnvironmentVariableW(n: LPCWSTR, v: LPCWSTR) -> BOOL;
                 pub fn GetEnvironmentStringsW() -> LPWCH;
                 pub fn FreeEnvironmentStringsW(env_ptr: LPWCH) -> BOOL;
                 pub fn GetModuleFileNameW(hModule: HMODULE,
@@ -6401,8 +7004,7 @@ pub mod funcs {
                                           nSize: DWORD)
                                           -> DWORD;
                 pub fn CreateDirectoryW(lpPathName: LPCWSTR,
-                                        lpSecurityAttributes:
-                                        LPSECURITY_ATTRIBUTES)
+                                        lpSecurityAttributes: LPSECURITY_ATTRIBUTES)
                                         -> BOOL;
                 pub fn CopyFileW(lpExistingFileName: LPCWSTR,
                                  lpNewFileName: LPCWSTR,
@@ -6410,15 +7012,13 @@ pub mod funcs {
                                  -> BOOL;
                 pub fn DeleteFileW(lpPathName: LPCWSTR) -> BOOL;
                 pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL;
-                pub fn GetCurrentDirectoryW(nBufferLength: DWORD,
-                                            lpBuffer: LPWSTR)
-                                            -> DWORD;
+                pub fn GetCurrentDirectoryW(nBufferLength: DWORD, lpBuffer: LPWSTR) -> DWORD;
                 pub fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL;
                 pub fn GetLastError() -> DWORD;
-                pub fn FindFirstFileW(fileName: LPCWSTR, findFileData: LPWIN32_FIND_DATAW)
+                pub fn FindFirstFileW(fileName: LPCWSTR,
+                                      findFileData: LPWIN32_FIND_DATAW)
                                       -> HANDLE;
-                pub fn FindNextFileW(findFile: HANDLE, findFileData: LPWIN32_FIND_DATAW)
-                                     -> BOOL;
+                pub fn FindNextFileW(findFile: HANDLE, findFileData: LPWIN32_FIND_DATAW) -> BOOL;
                 pub fn FindClose(findFile: HANDLE) -> BOOL;
                 pub fn DuplicateHandle(hSourceProcessHandle: HANDLE,
                                        hSourceHandle: HANDLE,
@@ -6436,39 +7036,27 @@ pub mod funcs {
                 pub fn GetCurrentProcess() -> HANDLE;
                 pub fn CreateProcessW(lpApplicationName: LPCWSTR,
                                       lpCommandLine: LPWSTR,
-                                      lpProcessAttributes:
-                                      LPSECURITY_ATTRIBUTES,
-                                      lpThreadAttributes:
-                                      LPSECURITY_ATTRIBUTES,
+                                      lpProcessAttributes: LPSECURITY_ATTRIBUTES,
+                                      lpThreadAttributes: LPSECURITY_ATTRIBUTES,
                                       bInheritHandles: BOOL,
                                       dwCreationFlags: DWORD,
                                       lpEnvironment: LPVOID,
                                       lpCurrentDirectory: LPCWSTR,
                                       lpStartupInfo: LPSTARTUPINFO,
-                                      lpProcessInformation:
-                                      LPPROCESS_INFORMATION)
+                                      lpProcessInformation: LPPROCESS_INFORMATION)
                                       -> BOOL;
-                pub fn WaitForSingleObject(hHandle: HANDLE,
-                                           dwMilliseconds: DWORD)
-                                           -> DWORD;
-                pub fn TerminateProcess(hProcess: HANDLE, uExitCode: c_uint)
-                                        -> BOOL;
-                pub fn GetExitCodeProcess(hProcess: HANDLE,
-                                          lpExitCode: LPDWORD)
-                                          -> BOOL;
+                pub fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
+                pub fn TerminateProcess(hProcess: HANDLE, uExitCode: c_uint) -> BOOL;
+                pub fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: LPDWORD) -> BOOL;
                 pub fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO);
                 pub fn VirtualAlloc(lpAddress: LPVOID,
                                     dwSize: SIZE_T,
                                     flAllocationType: DWORD,
                                     flProtect: DWORD)
                                     -> LPVOID;
-                pub fn VirtualFree(lpAddress: LPVOID,
-                                   dwSize: SIZE_T,
-                                   dwFreeType: DWORD)
-                                   -> BOOL;
+                pub fn VirtualFree(lpAddress: LPVOID, dwSize: SIZE_T, dwFreeType: DWORD) -> BOOL;
                 pub fn VirtualLock(lpAddress: LPVOID, dwSize: SIZE_T) -> BOOL;
-                pub fn VirtualUnlock(lpAddress: LPVOID, dwSize: SIZE_T)
-                                     -> BOOL;
+                pub fn VirtualUnlock(lpAddress: LPVOID, dwSize: SIZE_T) -> BOOL;
                 pub fn VirtualProtect(lpAddress: LPVOID,
                                       dwSize: SIZE_T,
                                       flNewProtect: DWORD,
@@ -6494,11 +7082,12 @@ pub mod funcs {
                 pub fn UnmapViewOfFile(lpBaseAddress: LPCVOID) -> BOOL;
                 pub fn MoveFileExW(lpExistingFileName: LPCWSTR,
                                    lpNewFileName: LPCWSTR,
-                                   dwFlags: DWORD) -> BOOL;
+                                   dwFlags: DWORD)
+                                   -> BOOL;
                 pub fn CreateHardLinkW(lpSymlinkFileName: LPCWSTR,
                                        lpTargetFileName: LPCWSTR,
                                        lpSecurityAttributes: LPSECURITY_ATTRIBUTES)
-                                        -> BOOL;
+                                       -> BOOL;
                 pub fn FlushFileBuffers(hFile: HANDLE) -> BOOL;
                 pub fn CreateFileW(lpFileName: LPCWSTR,
                                    dwDesiredAccess: DWORD,
@@ -6506,59 +7095,59 @@ pub mod funcs {
                                    lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
                                    dwCreationDisposition: DWORD,
                                    dwFlagsAndAttributes: DWORD,
-                                   hTemplateFile: HANDLE) -> HANDLE;
+                                   hTemplateFile: HANDLE)
+                                   -> HANDLE;
                 pub fn ReadFile(hFile: HANDLE,
                                 lpBuffer: LPVOID,
                                 nNumberOfBytesToRead: DWORD,
                                 lpNumberOfBytesRead: LPDWORD,
-                                lpOverlapped: LPOVERLAPPED) -> BOOL;
+                                lpOverlapped: LPOVERLAPPED)
+                                -> BOOL;
                 pub fn WriteFile(hFile: HANDLE,
                                  lpBuffer: LPVOID,
                                  nNumberOfBytesToWrite: DWORD,
                                  lpNumberOfBytesWritten: LPDWORD,
-                                 lpOverlapped: LPOVERLAPPED) -> BOOL;
+                                 lpOverlapped: LPOVERLAPPED)
+                                 -> BOOL;
                 pub fn SetFilePointerEx(hFile: HANDLE,
                                         liDistanceToMove: LARGE_INTEGER,
                                         lpNewFilePointer: PLARGE_INTEGER,
-                                        dwMoveMethod: DWORD) -> BOOL;
+                                        dwMoveMethod: DWORD)
+                                        -> BOOL;
                 pub fn SetEndOfFile(hFile: HANDLE) -> BOOL;
 
-                pub fn GetSystemTimeAsFileTime(
-                            lpSystemTimeAsFileTime: LPFILETIME);
+                pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME);
 
-                pub fn QueryPerformanceFrequency(
-                            lpFrequency: *mut LARGE_INTEGER) -> BOOL;
-                pub fn QueryPerformanceCounter(
-                            lpPerformanceCount: *mut LARGE_INTEGER) -> BOOL;
+                pub fn QueryPerformanceFrequency(lpFrequency: *mut LARGE_INTEGER) -> BOOL;
+                pub fn QueryPerformanceCounter(lpPerformanceCount: *mut LARGE_INTEGER) -> BOOL;
 
                 pub fn GetCurrentProcessId() -> DWORD;
-                pub fn CreateNamedPipeW(
-                            lpName: LPCWSTR,
-                            dwOpenMode: DWORD,
-                            dwPipeMode: DWORD,
-                            nMaxInstances: DWORD,
-                            nOutBufferSize: DWORD,
-                            nInBufferSize: DWORD,
-                            nDefaultTimeOut: DWORD,
-                            lpSecurityAttributes: LPSECURITY_ATTRIBUTES
-                            ) -> HANDLE;
-                pub fn ConnectNamedPipe(hNamedPipe: HANDLE,
-                                        lpOverlapped: LPOVERLAPPED) -> BOOL;
-                pub fn WaitNamedPipeW(lpNamedPipeName: LPCWSTR,
-                                      nTimeOut: DWORD) -> BOOL;
+                pub fn CreateNamedPipeW(lpName: LPCWSTR,
+                                        dwOpenMode: DWORD,
+                                        dwPipeMode: DWORD,
+                                        nMaxInstances: DWORD,
+                                        nOutBufferSize: DWORD,
+                                        nInBufferSize: DWORD,
+                                        nDefaultTimeOut: DWORD,
+                                        lpSecurityAttributes: LPSECURITY_ATTRIBUTES)
+                                        -> HANDLE;
+                pub fn ConnectNamedPipe(hNamedPipe: HANDLE, lpOverlapped: LPOVERLAPPED) -> BOOL;
+                pub fn WaitNamedPipeW(lpNamedPipeName: LPCWSTR, nTimeOut: DWORD) -> BOOL;
                 pub fn SetNamedPipeHandleState(hNamedPipe: HANDLE,
                                                lpMode: LPDWORD,
                                                lpMaxCollectionCount: LPDWORD,
                                                lpCollectDataTimeout: LPDWORD)
-                                                            -> BOOL;
+                                               -> BOOL;
                 pub fn CreateEventW(lpEventAttributes: LPSECURITY_ATTRIBUTES,
                                     bManualReset: BOOL,
                                     bInitialState: BOOL,
-                                    lpName: LPCWSTR) -> HANDLE;
+                                    lpName: LPCWSTR)
+                                    -> HANDLE;
                 pub fn GetOverlappedResult(hFile: HANDLE,
                                            lpOverlapped: LPOVERLAPPED,
                                            lpNumberOfBytesTransferred: LPDWORD,
-                                           bWait: BOOL) -> BOOL;
+                                           bWait: BOOL)
+                                           -> BOOL;
                 pub fn DisconnectNamedPipe(hNamedPipe: HANDLE) -> BOOL;
             }
         }
@@ -6575,8 +7164,7 @@ pub mod funcs {
                 pub fn get_osfhandle(fd: c_int) -> c_long;
 
                 #[link_name = "_open_osfhandle"]
-                pub fn open_osfhandle(osfhandle: intptr_t,
-                                      flags: c_int) -> c_int;
+                pub fn open_osfhandle(osfhandle: intptr_t, flags: c_int) -> c_int;
             }
         }
 
@@ -6591,4 +7179,6 @@ pub mod funcs {
     }
 }
 
-#[test] fn work_on_windows() { } // FIXME #10872 needed for a happy windows
+#[test]
+fn work_on_windows() {
+} // FIXME #10872 needed for a happy windows
index 362303869d78ddcbb17d03c0ab870130d88499e1..3958969cfca3200936f2143e2297b792f2180814 100644 (file)
@@ -17,15 +17,17 @@ pub struct LogDirective {
     pub level: u32,
 }
 
-pub const LOG_LEVEL_NAMES: [&'static str; 4] = ["ERROR", "WARN", "INFO",
-                                               "DEBUG"];
+pub const LOG_LEVEL_NAMES: [&'static str; 4] = ["ERROR", "WARN", "INFO", "DEBUG"];
 
 /// Parse an individual log level that is either a number or a symbolic log level
 fn parse_log_level(level: &str) -> Option<u32> {
-    level.parse::<u32>().ok().or_else(|| {
-        let pos = LOG_LEVEL_NAMES.iter().position(|&name| name.eq_ignore_ascii_case(level));
-        pos.map(|p| p as u32 + 1)
-    }).map(|p| cmp::min(p, ::MAX_LOG_LEVEL))
+    level.parse::<u32>()
+         .ok()
+         .or_else(|| {
+             let pos = LOG_LEVEL_NAMES.iter().position(|&name| name.eq_ignore_ascii_case(level));
+             pos.map(|p| p as u32 + 1)
+         })
+         .map(|p| cmp::min(p, ::MAX_LOG_LEVEL))
 }
 
 /// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1/foo")
@@ -40,44 +42,48 @@ pub fn parse_logging_spec(spec: &str) -> (Vec<LogDirective>, Option<String>) {
     let mods = parts.next();
     let filter = parts.next();
     if parts.next().is_some() {
-        println!("warning: invalid logging spec '{}', \
-                 ignoring it (too many '/'s)", spec);
+        println!("warning: invalid logging spec '{}', ignoring it (too many '/'s)",
+                 spec);
         return (dirs, None);
     }
-    mods.map(|m| { for s in m.split(',') {
-        if s.is_empty() { continue }
-        let mut parts = s.split('=');
-        let (log_level, name) = match (parts.next(), parts.next().map(|s| s.trim()), parts.next()) {
-            (Some(part0), None, None) => {
-                // if the single argument is a log-level string or number,
-                // treat that as a global fallback
-                match parse_log_level(part0) {
-                    Some(num) => (num, None),
-                    None => (::MAX_LOG_LEVEL, Some(part0)),
-                }
+    if let Some(m) = mods {
+        for s in m.split(',') {
+            if s.is_empty() {
+                continue
             }
-            (Some(part0), Some(""), None) => (::MAX_LOG_LEVEL, Some(part0)),
-            (Some(part0), Some(part1), None) => {
-                match parse_log_level(part1) {
-                    Some(num) => (num, Some(part0)),
-                    _ => {
-                        println!("warning: invalid logging spec '{}', \
-                                 ignoring it", part1);
-                        continue
+            let mut parts = s.split('=');
+            let (log_level, name) = match (parts.next(),
+                                           parts.next().map(|s| s.trim()),
+                                           parts.next()) {
+                (Some(part0), None, None) => {
+                    // if the single argument is a log-level string or number,
+                    // treat that as a global fallback
+                    match parse_log_level(part0) {
+                        Some(num) => (num, None),
+                        None => (::MAX_LOG_LEVEL, Some(part0)),
                     }
                 }
-            },
-            _ => {
-                println!("warning: invalid logging spec '{}', \
-                         ignoring it", s);
-                continue
-            }
-        };
-        dirs.push(LogDirective {
-            name: name.map(str::to_owned),
-            level: log_level,
-        });
-    }});
+                (Some(part0), Some(""), None) => (::MAX_LOG_LEVEL, Some(part0)),
+                (Some(part0), Some(part1), None) => {
+                    match parse_log_level(part1) {
+                        Some(num) => (num, Some(part0)),
+                        _ => {
+                            println!("warning: invalid logging spec '{}', ignoring it", part1);
+                            continue
+                        }
+                    }
+                }
+                _ => {
+                    println!("warning: invalid logging spec '{}', ignoring it", s);
+                    continue
+                }
+            };
+            dirs.push(LogDirective {
+                name: name.map(str::to_owned),
+                level: log_level,
+            });
+        }
+    }
 
     (dirs, filter.map(str::to_owned))
 }
index 2c91a88f6ec9e8a5efd561757d0d321cb47ee7e3..9cb835bd8525d583c99eab127bd178f5048ad2cb 100644 (file)
@@ -235,7 +235,9 @@ pub trait Logger {
     fn log(&mut self, record: &LogRecord);
 }
 
-struct DefaultLogger { handle: Stderr }
+struct DefaultLogger {
+    handle: Stderr,
+}
 
 /// Wraps the log level with fmt implementations.
 #[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
@@ -246,7 +248,7 @@ impl fmt::Display for LogLevel {
         let LogLevel(level) = *self;
         match LOG_LEVEL_NAMES.get(level as usize - 1) {
             Some(ref name) => fmt::Display::fmt(name, fmt),
-            None => fmt::Display::fmt(&level, fmt)
+            None => fmt::Display::fmt(&level, fmt),
         }
     }
 }
@@ -301,11 +303,10 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
     // Completely remove the local logger from TLS in case anyone attempts to
     // frob the slot while we're doing the logging. This will destroy any logger
     // set during logging.
-    let mut logger: Box<Logger + Send> = LOCAL_LOGGER.with(|s| {
-        s.borrow_mut().take()
-    }).unwrap_or_else(|| {
-        box DefaultLogger { handle: io::stderr() }
-    });
+    let mut logger: Box<Logger + Send> = LOCAL_LOGGER.with(|s| s.borrow_mut().take())
+                                                     .unwrap_or_else(|| {
+                                                         box DefaultLogger { handle: io::stderr() }
+                                                     });
     logger.log(&LogRecord {
         level: LogLevel(level),
         args: args,
@@ -320,22 +321,20 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
 /// safely
 #[doc(hidden)]
 #[inline(always)]
-pub fn log_level() -> u32 { unsafe { LOG_LEVEL } }
+pub fn log_level() -> u32 {
+    unsafe { LOG_LEVEL }
+}
 
 /// Replaces the thread-local logger with the specified logger, returning the old
 /// logger.
 pub fn set_logger(logger: Box<Logger + Send>) -> Option<Box<Logger + Send>> {
-    let mut l = Some(logger);
-    LOCAL_LOGGER.with(|slot| {
-        mem::replace(&mut *slot.borrow_mut(), l.take())
-    })
+    LOCAL_LOGGER.with(|slot| mem::replace(&mut *slot.borrow_mut(), Some(logger)))
 }
 
 /// A LogRecord is created by the logging macros, and passed as the only
 /// argument to Loggers.
 #[derive(Debug)]
 pub struct LogRecord<'a> {
-
     /// The module path of where the LogRecord originated.
     pub module_path: &'a str,
 
@@ -373,7 +372,9 @@ pub fn mod_enabled(level: u32, module: &str) -> bool {
     // again to whether they should really be here or not. Hence, despite this
     // check being expanded manually in the logging macro, this function checks
     // the log level again.
-    if level > unsafe { LOG_LEVEL } { return false }
+    if level > unsafe { LOG_LEVEL } {
+        return false
+    }
 
     // This assertion should never get tripped unless we're in an at_exit
     // handler after logging has been torn down and a logging attempt was made.
@@ -385,14 +386,11 @@ pub fn mod_enabled(level: u32, module: &str) -> bool {
     }
 }
 
-fn enabled(level: u32,
-           module: &str,
-           iter: slice::Iter<directive::LogDirective>)
-           -> bool {
+fn enabled(level: u32, module: &str, iter: slice::Iter<directive::LogDirective>) -> bool {
     // Search for the longest match, the vector is assumed to be pre-sorted.
     for directive in iter.rev() {
         match directive.name {
-            Some(ref name) if !module.starts_with(&name[..]) => {},
+            Some(ref name) if !module.starts_with(&name[..]) => {}
             Some(..) | None => {
                 return level <= directive.level
             }
@@ -445,16 +443,14 @@ mod tests {
 
     #[test]
     fn match_full_path() {
-        let dirs = [
-            LogDirective {
-                name: Some("crate2".to_string()),
-                level: 3
-            },
-            LogDirective {
-                name: Some("crate1::mod1".to_string()),
-                level: 2
-            }
-        ];
+        let dirs = [LogDirective {
+                        name: Some("crate2".to_string()),
+                        level: 3,
+                    },
+                    LogDirective {
+                        name: Some("crate1::mod1".to_string()),
+                        level: 2,
+                    }];
         assert!(enabled(2, "crate1::mod1", dirs.iter()));
         assert!(!enabled(3, "crate1::mod1", dirs.iter()));
         assert!(enabled(3, "crate2", dirs.iter()));
@@ -463,49 +459,72 @@ mod tests {
 
     #[test]
     fn no_match() {
-        let dirs = [
-            LogDirective { name: Some("crate2".to_string()), level: 3 },
-            LogDirective { name: Some("crate1::mod1".to_string()), level: 2 }
-        ];
+        let dirs = [LogDirective {
+                        name: Some("crate2".to_string()),
+                        level: 3,
+                    },
+                    LogDirective {
+                        name: Some("crate1::mod1".to_string()),
+                        level: 2,
+                    }];
         assert!(!enabled(2, "crate3", dirs.iter()));
     }
 
     #[test]
     fn match_beginning() {
-        let dirs = [
-            LogDirective { name: Some("crate2".to_string()), level: 3 },
-            LogDirective { name: Some("crate1::mod1".to_string()), level: 2 }
-        ];
+        let dirs = [LogDirective {
+                        name: Some("crate2".to_string()),
+                        level: 3,
+                    },
+                    LogDirective {
+                        name: Some("crate1::mod1".to_string()),
+                        level: 2,
+                    }];
         assert!(enabled(3, "crate2::mod1", dirs.iter()));
     }
 
     #[test]
     fn match_beginning_longest_match() {
-        let dirs = [
-            LogDirective { name: Some("crate2".to_string()), level: 3 },
-            LogDirective { name: Some("crate2::mod".to_string()), level: 4 },
-            LogDirective { name: Some("crate1::mod1".to_string()), level: 2 }
-        ];
+        let dirs = [LogDirective {
+                        name: Some("crate2".to_string()),
+                        level: 3,
+                    },
+                    LogDirective {
+                        name: Some("crate2::mod".to_string()),
+                        level: 4,
+                    },
+                    LogDirective {
+                        name: Some("crate1::mod1".to_string()),
+                        level: 2,
+                    }];
         assert!(enabled(4, "crate2::mod1", dirs.iter()));
         assert!(!enabled(4, "crate2", dirs.iter()));
     }
 
     #[test]
     fn match_default() {
-        let dirs = [
-            LogDirective { name: None, level: 3 },
-            LogDirective { name: Some("crate1::mod1".to_string()), level: 2 }
-        ];
+        let dirs = [LogDirective {
+                        name: None,
+                        level: 3,
+                    },
+                    LogDirective {
+                        name: Some("crate1::mod1".to_string()),
+                        level: 2,
+                    }];
         assert!(enabled(2, "crate1::mod1", dirs.iter()));
         assert!(enabled(3, "crate2::mod2", dirs.iter()));
     }
 
     #[test]
     fn zero_level() {
-        let dirs = [
-            LogDirective { name: None, level: 3 },
-            LogDirective { name: Some("crate1::mod1".to_string()), level: 0 }
-        ];
+        let dirs = [LogDirective {
+                        name: None,
+                        level: 3,
+                    },
+                    LogDirective {
+                        name: Some("crate1::mod1".to_string()),
+                        level: 0,
+                    }];
         assert!(!enabled(1, "crate1::mod1", dirs.iter()));
         assert!(enabled(3, "crate2::mod2", dirs.iter()));
     }
index db81ff5c0700dc4e1c176ec36e4a0dc5e36a6505..411ca8360805440c215a76c437a461558d6e0fdf 100644 (file)
@@ -27,15 +27,15 @@ const CHACHA_ROUNDS: usize = 20; // Cryptographically secure from 8 upwards as o
 /// Salsa20*](http://cr.yp.to/chacha.html)
 #[derive(Copy, Clone)]
 pub struct ChaChaRng {
-    buffer:  [u32; STATE_WORDS], // Internal buffer of output
-    state:   [u32; STATE_WORDS], // Initial state
-    index:   usize,                 // Index into state
+    buffer: [u32; STATE_WORDS], // Internal buffer of output
+    state: [u32; STATE_WORDS], // Initial state
+    index: usize, // Index into state
 }
 
 static EMPTY: ChaChaRng = ChaChaRng {
-    buffer:  [0; STATE_WORDS],
-    state:   [0; STATE_WORDS],
-    index:   STATE_WORDS
+    buffer: [0; STATE_WORDS],
+    state: [0; STATE_WORDS],
+    index: STATE_WORDS,
 };
 
 
@@ -95,9 +95,9 @@ impl ChaChaRng {
     /// associated with a particular nonce can call this function with
     /// arguments `0, desired_nonce`.
     pub fn set_counter(&mut self, counter_low: u64, counter_high: u64) {
-        self.state[12] = (counter_low >>  0) as u32;
+        self.state[12] = (counter_low >> 0) as u32;
         self.state[13] = (counter_low >> 32) as u32;
-        self.state[14] = (counter_high >>  0) as u32;
+        self.state[14] = (counter_high >> 0) as u32;
         self.state[15] = (counter_high >> 32) as u32;
         self.index = STATE_WORDS; // force recomputation
     }
@@ -127,7 +127,7 @@ impl ChaChaRng {
         self.state[3] = 0x6B206574;
 
         for i in 0..KEY_WORDS {
-            self.state[4+i] = key[i];
+            self.state[4 + i] = key[i];
         }
 
         self.state[12] = 0;
@@ -144,11 +144,17 @@ impl ChaChaRng {
         self.index = 0;
         // update 128-bit counter
         self.state[12] += 1;
-        if self.state[12] != 0 { return };
+        if self.state[12] != 0 {
+            return;
+        }
         self.state[13] += 1;
-        if self.state[13] != 0 { return };
+        if self.state[13] != 0 {
+            return;
+        }
         self.state[14] += 1;
-        if self.state[14] != 0 { return };
+        if self.state[14] != 0 {
+            return;
+        }
         self.state[15] += 1;
     }
 }
@@ -172,7 +178,7 @@ impl<'a> SeedableRng<&'a [u32]> for ChaChaRng {
         // reset state
         self.init(&[0; KEY_WORDS]);
         // set key in place
-        let key = &mut self.state[4 .. 4+KEY_WORDS];
+        let key = &mut self.state[4..4 + KEY_WORDS];
         for (k, s) in key.iter_mut().zip(seed) {
             *k = *s;
         }
@@ -191,7 +197,7 @@ impl<'a> SeedableRng<&'a [u32]> for ChaChaRng {
 
 impl Rand for ChaChaRng {
     fn rand<R: Rng>(other: &mut R) -> ChaChaRng {
-        let mut key : [u32; KEY_WORDS] = [0; KEY_WORDS];
+        let mut key: [u32; KEY_WORDS] = [0; KEY_WORDS];
         for word in &mut key {
             *word = other.gen();
         }
@@ -219,7 +225,7 @@ mod tests {
 
     #[test]
     fn test_rng_seeded() {
-        let seed : &[_] = &[0,1,2,3,4,5,6,7];
+        let seed: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
         let mut ra: ChaChaRng = SeedableRng::from_seed(seed);
         let mut rb: ChaChaRng = SeedableRng::from_seed(seed);
         assert!(order::equals(ra.gen_ascii_chars().take(100),
@@ -239,10 +245,11 @@ mod tests {
     }
 
     #[test]
+    #[rustfmt_skip]
     fn test_rng_true_values() {
         // Test vectors 1 and 2 from
         // http://tools.ietf.org/html/draft-nir-cfrg-chacha20-poly1305-04
-        let seed : &[_] = &[0; 8];
+        let seed: &[_] = &[0; 8];
         let mut ra: ChaChaRng = SeedableRng::from_seed(seed);
 
         let v = (0..16).map(|_| ra.next_u32()).collect::<Vec<_>>();
@@ -260,12 +267,12 @@ mod tests {
                         0x281fed31, 0x45fb0a51, 0x1f0ae1ac, 0x6f4d794b));
 
 
-        let seed : &[_] = &[0,1,2,3,4,5,6,7];
+        let seed: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
         let mut ra: ChaChaRng = SeedableRng::from_seed(seed);
 
         // Store the 17*i-th 32-bit word,
         // i.e., the i-th word of the i-th 16-word block
-        let mut v : Vec<u32> = Vec::new();
+        let mut v: Vec<u32> = Vec::new();
         for _ in 0..16 {
             v.push(ra.next_u32());
             for _ in 0..16 {
@@ -282,7 +289,7 @@ mod tests {
 
     #[test]
     fn test_rng_clone() {
-        let seed : &[_] = &[0; 8];
+        let seed: &[_] = &[0; 8];
         let mut rng: ChaChaRng = SeedableRng::from_seed(seed);
         let mut clone = rng.clone();
         for _ in 0..16 {
index ce72fa08a73de728ed3193a419d3556bf0fb1dcb..f02b945178fb9ac905828b1cdac371d717145d4c 100644 (file)
@@ -35,20 +35,22 @@ pub struct Exp1(pub f64);
 // This could be done via `-rng.gen::<f64>().ln()` but that is slower.
 impl Rand for Exp1 {
     #[inline]
-    fn rand<R:Rng>(rng: &mut R) -> Exp1 {
+    fn rand<R: Rng>(rng: &mut R) -> Exp1 {
         #[inline]
         fn pdf(x: f64) -> f64 {
             (-x).exp()
         }
         #[inline]
-        fn zero_case<R:Rng>(rng: &mut R, _u: f64) -> f64 {
+        fn zero_case<R: Rng>(rng: &mut R, _u: f64) -> f64 {
             ziggurat_tables::ZIG_EXP_R - rng.gen::<f64>().ln()
         }
 
-        Exp1(ziggurat(rng, false,
+        Exp1(ziggurat(rng,
+                      false,
                       &ziggurat_tables::ZIG_EXP_X,
                       &ziggurat_tables::ZIG_EXP_F,
-                      pdf, zero_case))
+                      pdf,
+                      zero_case))
     }
 }
 
@@ -59,7 +61,7 @@ impl Rand for Exp1 {
 #[derive(Copy, Clone)]
 pub struct Exp {
     /// `lambda` stored as `1/lambda`, since this is what we scale by.
-    lambda_inverse: f64
+    lambda_inverse: f64,
 }
 
 impl Exp {
@@ -72,7 +74,9 @@ impl Exp {
 }
 
 impl Sample<f64> for Exp {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
+        self.ind_sample(rng)
+    }
 }
 impl IndependentSample<f64> for Exp {
     fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
@@ -83,8 +87,6 @@ impl IndependentSample<f64> for Exp {
 
 #[cfg(test)]
 mod tests {
-    use std::prelude::v1::*;
-
     use distributions::{Sample, IndependentSample};
     use super::Exp;
 
@@ -113,8 +115,6 @@ mod tests {
 mod bench {
     extern crate test;
 
-    use std::prelude::v1::*;
-
     use self::test::Bencher;
     use std::mem::size_of;
     use super::Exp;
index 2a5d4bbd2ec9db6818df0f201771fa148167cd8e..fceda64cbb3f195e2d251bb74c07a5afd3164146 100644 (file)
@@ -46,7 +46,7 @@ pub struct Gamma {
 enum GammaRepr {
     Large(GammaLargeShape),
     One(Exp),
-    Small(GammaSmallShape)
+    Small(GammaSmallShape),
 }
 
 // These two helpers could be made public, but saving the
@@ -65,7 +65,7 @@ enum GammaRepr {
 /// shape parameters.
 struct GammaSmallShape {
     inv_shape: f64,
-    large_shape: GammaLargeShape
+    large_shape: GammaLargeShape,
 }
 
 /// Gamma distribution where the shape parameter is larger than 1.
@@ -75,7 +75,7 @@ struct GammaSmallShape {
 struct GammaLargeShape {
     scale: f64,
     c: f64,
-    d: f64
+    d: f64,
 }
 
 impl Gamma {
@@ -88,9 +88,9 @@ impl Gamma {
         assert!(scale > 0.0, "Gamma::new called with scale <= 0");
 
         let repr = match shape {
-            1.0         => One(Exp::new(1.0 / scale)),
+            1.0 => One(Exp::new(1.0 / scale)),
             0.0 ... 1.0 => Small(GammaSmallShape::new_raw(shape, scale)),
-            _           => Large(GammaLargeShape::new_raw(shape, scale))
+            _ => Large(GammaLargeShape::new_raw(shape, scale)),
         };
         Gamma { repr: repr }
     }
@@ -100,7 +100,7 @@ impl GammaSmallShape {
     fn new_raw(shape: f64, scale: f64) -> GammaSmallShape {
         GammaSmallShape {
             inv_shape: 1. / shape,
-            large_shape: GammaLargeShape::new_raw(shape + 1.0, scale)
+            large_shape: GammaLargeShape::new_raw(shape + 1.0, scale),
         }
     }
 }
@@ -111,19 +111,25 @@ impl GammaLargeShape {
         GammaLargeShape {
             scale: scale,
             c: 1. / (9. * d).sqrt(),
-            d: d
+            d: d,
         }
     }
 }
 
 impl Sample<f64> for Gamma {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
+        self.ind_sample(rng)
+    }
 }
 impl Sample<f64> for GammaSmallShape {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
+        self.ind_sample(rng)
+    }
 }
 impl Sample<f64> for GammaLargeShape {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
+        self.ind_sample(rng)
+    }
 }
 
 impl IndependentSample<f64> for Gamma {
@@ -148,7 +154,7 @@ impl IndependentSample<f64> for GammaLargeShape {
             let StandardNormal(x) = rng.gen::<StandardNormal>();
             let v_cbrt = 1.0 + self.c * x;
             if v_cbrt <= 0.0 { // a^3 <= 0 iff a <= 0
-                continue
+                continue;
             }
 
             let v = v_cbrt * v_cbrt * v_cbrt;
@@ -156,8 +162,8 @@ impl IndependentSample<f64> for GammaLargeShape {
 
             let x_sqr = x * x;
             if u < 1.0 - 0.0331 * x_sqr * x_sqr ||
-                u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln()) {
-                return self.d * v * self.scale
+               u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln()) {
+                return self.d * v * self.scale;
             }
         }
     }
@@ -168,7 +174,7 @@ impl IndependentSample<f64> for GammaLargeShape {
 ///
 /// For `k > 0` integral, this distribution is the sum of the squares
 /// of `k` independent standard normal random variables. For other
-/// `k`, this uses the equivalent characterisation `χ²(k) = Gamma(k/2,
+/// `k`, this uses the equivalent characterization `χ²(k) = Gamma(k/2,
 /// 2)`.
 pub struct ChiSquared {
     repr: ChiSquaredRepr,
@@ -196,7 +202,9 @@ impl ChiSquared {
     }
 }
 impl Sample<f64> for ChiSquared {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
+        self.ind_sample(rng)
+    }
 }
 impl IndependentSample<f64> for ChiSquared {
     fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
@@ -206,7 +214,7 @@ impl IndependentSample<f64> for ChiSquared {
                 let StandardNormal(norm) = rng.gen::<StandardNormal>();
                 norm * norm
             }
-            DoFAnythingElse(ref g) => g.ind_sample(rng)
+            DoFAnythingElse(ref g) => g.ind_sample(rng),
         }
     }
 }
@@ -234,12 +242,14 @@ impl FisherF {
         FisherF {
             numer: ChiSquared::new(m),
             denom: ChiSquared::new(n),
-            dof_ratio: n / m
+            dof_ratio: n / m,
         }
     }
 }
 impl Sample<f64> for FisherF {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
+        self.ind_sample(rng)
+    }
 }
 impl IndependentSample<f64> for FisherF {
     fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
@@ -251,7 +261,7 @@ impl IndependentSample<f64> for FisherF {
 /// freedom.
 pub struct StudentT {
     chi: ChiSquared,
-    dof: f64
+    dof: f64,
 }
 
 impl StudentT {
@@ -261,12 +271,14 @@ impl StudentT {
         assert!(n > 0.0, "StudentT::new called with `n <= 0`");
         StudentT {
             chi: ChiSquared::new(n),
-            dof: n
+            dof: n,
         }
     }
 }
 impl Sample<f64> for StudentT {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
+        self.ind_sample(rng)
+    }
 }
 impl IndependentSample<f64> for StudentT {
     fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
@@ -277,8 +289,6 @@ impl IndependentSample<f64> for StudentT {
 
 #[cfg(test)]
 mod tests {
-    use std::prelude::v1::*;
-
     use distributions::{Sample, IndependentSample};
     use super::{ChiSquared, StudentT, FisherF};
 
@@ -339,7 +349,6 @@ mod tests {
 #[cfg(test)]
 mod bench {
     extern crate test;
-    use std::prelude::v1::*;
     use self::test::Bencher;
     use std::mem::size_of;
     use distributions::IndependentSample;
index 5defe174cf5d7f02e2bd189552f691ad6c7ba72d..4c62e1a350406ecd475d81ddebd838f466995b1f 100644 (file)
@@ -54,7 +54,9 @@ pub trait IndependentSample<Support>: Sample<Support> {
 
 /// A wrapper for generating types that implement `Rand` via the
 /// `Sample` & `IndependentSample` traits.
-pub struct RandSample<Sup> { _marker: PhantomData<Sup> }
+pub struct RandSample<Sup> {
+    _marker: PhantomData<Sup>,
+}
 
 impl<Sup> RandSample<Sup> {
     pub fn new() -> RandSample<Sup> {
@@ -63,7 +65,9 @@ impl<Sup> RandSample<Sup> {
 }
 
 impl<Sup: Rand> Sample<Sup> for RandSample<Sup> {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) }
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup {
+        self.ind_sample(rng)
+    }
 }
 
 impl<Sup: Rand> IndependentSample<Sup> for RandSample<Sup> {
@@ -89,9 +93,9 @@ pub struct Weighted<T> {
 /// `IndependentSample` traits. Note that `&T` is (cheaply) `Clone` for
 /// all `T`, as is `usize`, so one can store references or indices into
 /// another vector.
-pub struct WeightedChoice<'a, T:'a> {
+pub struct WeightedChoice<'a, T: 'a> {
     items: &'a mut [Weighted<T>],
-    weight_range: Range<usize>
+    weight_range: Range<usize>,
 }
 
 impl<'a, T: Clone> WeightedChoice<'a, T> {
@@ -103,7 +107,8 @@ impl<'a, T: Clone> WeightedChoice<'a, T> {
     /// - the total weight is larger than a `usize` can contain.
     pub fn new(items: &'a mut [Weighted<T>]) -> WeightedChoice<'a, T> {
         // strictly speaking, this is subsumed by the total weight == 0 case
-        assert!(!items.is_empty(), "WeightedChoice::new called with no items");
+        assert!(!items.is_empty(),
+                "WeightedChoice::new called with no items");
 
         let mut running_total = 0_usize;
 
@@ -113,25 +118,28 @@ impl<'a, T: Clone> WeightedChoice<'a, T> {
         for item in &mut *items {
             running_total = match running_total.checked_add(item.weight) {
                 Some(n) => n,
-                None => panic!("WeightedChoice::new called with a total weight \
-                               larger than a usize can contain")
+                None => panic!("WeightedChoice::new called with a total weight larger than a \
+                                usize can contain"),
             };
 
             item.weight = running_total;
         }
-        assert!(running_total != 0, "WeightedChoice::new called with a total weight of 0");
+        assert!(running_total != 0,
+                "WeightedChoice::new called with a total weight of 0");
 
         WeightedChoice {
             items: items,
             // we're likely to be generating numbers in this range
             // relatively often, so might as well cache it
-            weight_range: Range::new(0, running_total)
+            weight_range: Range::new(0, running_total),
         }
     }
 }
 
 impl<'a, T: Clone> Sample<T> for WeightedChoice<'a, T> {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> T { self.ind_sample(rng) }
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> T {
+        self.ind_sample(rng)
+    }
 }
 
 impl<'a, T: Clone> IndependentSample<T> for WeightedChoice<'a, T> {
@@ -195,14 +203,16 @@ mod ziggurat_tables;
 // the perf improvement (25-50%) is definitely worth the extra code
 // size from force-inlining.
 #[inline(always)]
-fn ziggurat<R: Rng, P, Z>(
-            rng: &mut R,
-            symmetric: bool,
-            x_tab: ziggurat_tables::ZigTable,
-            f_tab: ziggurat_tables::ZigTable,
-            mut pdf: P,
-            mut zero_case: Z)
-            -> f64 where P: FnMut(f64) -> f64, Z: FnMut(&mut R, f64) -> f64 {
+fn ziggurat<R: Rng, P, Z>(rng: &mut R,
+                          symmetric: bool,
+                          x_tab: ziggurat_tables::ZigTable,
+                          f_tab: ziggurat_tables::ZigTable,
+                          mut pdf: P,
+                          mut zero_case: Z)
+                          -> f64
+    where P: FnMut(f64) -> f64,
+          Z: FnMut(&mut R, f64) -> f64
+{
     const SCALE: f64 = (1u64 << 53) as f64;
     loop {
         // reimplement the f64 generation as an optimisation suggested
@@ -224,10 +234,18 @@ fn ziggurat<R: Rng, P, Z>(
 
         // u is either U(-1, 1) or U(0, 1) depending on if this is a
         // symmetric distribution or not.
-        let u = if symmetric {2.0 * f - 1.0} else {f};
+        let u = if symmetric {
+            2.0 * f - 1.0
+        } else {
+            f
+        };
         let x = u * x_tab[i];
 
-        let test_x = if symmetric { x.abs() } else {x};
+        let test_x = if symmetric {
+            x.abs()
+        } else {
+            x
+        };
 
         // algebraically equivalent to |u| < x_tab[i+1]/x_tab[i] (or u < x_tab[i+1]/x_tab[i])
         if test_x < x_tab[i + 1] {
@@ -245,8 +263,6 @@ fn ziggurat<R: Rng, P, Z>(
 
 #[cfg(test)]
 mod tests {
-    use std::prelude::v1::*;
-
     use {Rng, Rand};
     use super::{RandSample, WeightedChoice, Weighted, Sample, IndependentSample};
 
@@ -259,7 +275,9 @@ mod tests {
     }
 
     // 0, 1, 2, 3, ...
-    struct CountingRng { i: u32 }
+    struct CountingRng {
+        i: u32,
+    }
     impl Rng for CountingRng {
         fn next_u32(&mut self) -> u32 {
             self.i += 1;
@@ -278,6 +296,7 @@ mod tests {
         assert_eq!(rand_sample.ind_sample(&mut ::test::rng()), ConstRand(0));
     }
     #[test]
+    #[rustfmt_skip]
     fn test_weighted_choice() {
         // this makes assumptions about the internal implementation of
         // WeightedChoice, specifically: it doesn't reorder the items,
@@ -298,49 +317,55 @@ mod tests {
             }}
         }
 
-        t!(vec!(Weighted { weight: 1, item: 10}), [10]);
+        t!(vec!(Weighted { weight: 1, item: 10 }),
+           [10]);
 
         // skip some
-        t!(vec!(Weighted { weight: 0, item: 20},
-                Weighted { weight: 2, item: 21},
-                Weighted { weight: 0, item: 22},
-                Weighted { weight: 1, item: 23}),
-           [21,21, 23]);
+        t!(vec!(Weighted { weight: 0, item: 20 },
+                Weighted { weight: 2, item: 21 },
+                Weighted { weight: 0, item: 22 },
+                Weighted { weight: 1, item: 23 }),
+           [21, 21, 23]);
 
         // different weights
-        t!(vec!(Weighted { weight: 4, item: 30},
-                Weighted { weight: 3, item: 31}),
-           [30,30,30,30, 31,31,31]);
+        t!(vec!(Weighted { weight: 4, item: 30 },
+                Weighted { weight: 3, item: 31 }),
+           [30, 30, 30, 30, 31, 31, 31]);
 
         // check that we're binary searching
         // correctly with some vectors of odd
         // length.
-        t!(vec!(Weighted { weight: 1, item: 40},
-                Weighted { weight: 1, item: 41},
-                Weighted { weight: 1, item: 42},
-                Weighted { weight: 1, item: 43},
-                Weighted { weight: 1, item: 44}),
+        t!(vec!(Weighted { weight: 1, item: 40 },
+                Weighted { weight: 1, item: 41 },
+                Weighted { weight: 1, item: 42 },
+                Weighted { weight: 1, item: 43 },
+                Weighted { weight: 1, item: 44 }),
            [40, 41, 42, 43, 44]);
-        t!(vec!(Weighted { weight: 1, item: 50},
-                Weighted { weight: 1, item: 51},
-                Weighted { weight: 1, item: 52},
-                Weighted { weight: 1, item: 53},
-                Weighted { weight: 1, item: 54},
-                Weighted { weight: 1, item: 55},
-                Weighted { weight: 1, item: 56}),
+        t!(vec!(Weighted { weight: 1, item: 50 },
+                Weighted { weight: 1, item: 51 },
+                Weighted { weight: 1, item: 52 },
+                Weighted { weight: 1, item: 53 },
+                Weighted { weight: 1, item: 54 },
+                Weighted { weight: 1, item: 55 },
+                Weighted { weight: 1, item: 56 }),
            [50, 51, 52, 53, 54, 55, 56]);
     }
 
-    #[test] #[should_panic]
+    #[test]
+    #[should_panic]
     fn test_weighted_choice_no_items() {
         WeightedChoice::<isize>::new(&mut []);
     }
-    #[test] #[should_panic]
+    #[test]
+    #[should_panic]
+    #[rustfmt_skip]
     fn test_weighted_choice_zero_weight() {
-        WeightedChoice::new(&mut [Weighted { weight: 0, item: 0},
-                                  Weighted { weight: 0, item: 1}]);
+        WeightedChoice::new(&mut [Weighted { weight: 0, item: 0 },
+                                  Weighted { weight: 0, item: 1 }]);
     }
-    #[test] #[should_panic]
+    #[test]
+    #[should_panic]
+    #[rustfmt_skip]
     fn test_weighted_choice_weight_overflows() {
         let x = (!0) as usize / 2; // x + x + 2 is the overflow
         WeightedChoice::new(&mut [Weighted { weight: x, item: 0 },
index cc70a695c8d594c1ab85cac67006c7a1ad77cd5c..b2ccc5eb6095baed6558f2dff31e534f642a6069 100644 (file)
@@ -32,13 +32,13 @@ use distributions::{ziggurat, ziggurat_tables, Sample, IndependentSample};
 pub struct StandardNormal(pub f64);
 
 impl Rand for StandardNormal {
-    fn rand<R:Rng>(rng: &mut R) -> StandardNormal {
+    fn rand<R: Rng>(rng: &mut R) -> StandardNormal {
         #[inline]
         fn pdf(x: f64) -> f64 {
-            (-x*x/2.0).exp()
+            (-x * x / 2.0).exp()
         }
         #[inline]
-        fn zero_case<R:Rng>(rng: &mut R, u: f64) -> f64 {
+        fn zero_case<R: Rng>(rng: &mut R, u: f64) -> f64 {
             // compute a random number in the tail by hand
 
             // strange initial conditions, because the loop is not
@@ -56,15 +56,19 @@ impl Rand for StandardNormal {
                 y = y_.ln();
             }
 
-            if u < 0.0 { x - ziggurat_tables::ZIG_NORM_R } else { ziggurat_tables::ZIG_NORM_R - x }
+            if u < 0.0 {
+                x - ziggurat_tables::ZIG_NORM_R
+            } else {
+                ziggurat_tables::ZIG_NORM_R - x
+            }
         }
 
-        StandardNormal(ziggurat(
-            rng,
-            true, // this is symmetric
-            &ziggurat_tables::ZIG_NORM_X,
-            &ziggurat_tables::ZIG_NORM_F,
-            pdf, zero_case))
+        StandardNormal(ziggurat(rng,
+                                true, // this is symmetric
+                                &ziggurat_tables::ZIG_NORM_X,
+                                &ziggurat_tables::ZIG_NORM_F,
+                                pdf,
+                                zero_case))
     }
 }
 
@@ -89,12 +93,14 @@ impl Normal {
         assert!(std_dev >= 0.0, "Normal::new called with `std_dev` < 0");
         Normal {
             mean: mean,
-            std_dev: std_dev
+            std_dev: std_dev,
         }
     }
 }
 impl Sample<f64> for Normal {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
+        self.ind_sample(rng)
+    }
 }
 impl IndependentSample<f64> for Normal {
     fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
@@ -110,7 +116,7 @@ impl IndependentSample<f64> for Normal {
 /// std_dev**2)` distributed.
 #[derive(Copy, Clone)]
 pub struct LogNormal {
-    norm: Normal
+    norm: Normal,
 }
 
 impl LogNormal {
@@ -126,7 +132,9 @@ impl LogNormal {
     }
 }
 impl Sample<f64> for LogNormal {
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 {
+        self.ind_sample(rng)
+    }
 }
 impl IndependentSample<f64> for LogNormal {
     fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
@@ -136,8 +144,6 @@ impl IndependentSample<f64> for LogNormal {
 
 #[cfg(test)]
 mod tests {
-    use std::prelude::v1::*;
-
     use distributions::{Sample, IndependentSample};
     use super::{Normal, LogNormal};
 
@@ -176,10 +182,9 @@ mod tests {
 #[cfg(test)]
 mod bench {
     extern crate test;
-    use std::prelude::v1::*;
     use self::test::Bencher;
     use std::mem::size_of;
-    use distributions::{Sample};
+    use distributions::Sample;
     use super::Normal;
 
     #[bench]
index 26f92ee3b1cf079641a9e3dcd727d856c7a93593..f94ef059dae8fc2a5f6fe5f57d0069e30825cd05 100644 (file)
@@ -32,7 +32,7 @@ use distributions::{Sample, IndependentSample};
 pub struct Range<X> {
     low: X,
     range: X,
-    accept_zone: X
+    accept_zone: X,
 }
 
 impl<X: SampleRange + PartialOrd> Range<X> {
@@ -46,7 +46,9 @@ impl<X: SampleRange + PartialOrd> Range<X> {
 
 impl<Sup: SampleRange> Sample<Sup> for Range<Sup> {
     #[inline]
-    fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) }
+    fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup {
+        self.ind_sample(rng)
+    }
 }
 impl<Sup: SampleRange> IndependentSample<Sup> for Range<Sup> {
     fn ind_sample<R: Rng>(&self, rng: &mut R) -> Sup {
@@ -146,9 +148,8 @@ float_impl! { f64 }
 
 #[cfg(test)]
 mod tests {
-    use std::prelude::v1::*;
     use distributions::{Sample, IndependentSample};
-    use super::Range as Range;
+    use super::Range;
 
     #[should_panic]
     #[test]
@@ -182,8 +183,7 @@ mod tests {
                  )*
             }}
         }
-        t!(i8, i16, i32, i64, isize,
-           u8, u16, u32, u64, usize)
+        t!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize)
     }
 
     #[test]
index b6de4bf892cdfb658def734e365de8eaf9aa0bea..7dfb0f131a2c50bde150dbc0ebcee01859b49c53 100644 (file)
@@ -13,6 +13,7 @@
 
 pub type ZigTable = &'static [f64; 257];
 pub const ZIG_NORM_R: f64 = 3.654152885361008796;
+#[rustfmt_skip]
 pub static ZIG_NORM_X: [f64; 257] =
     [3.910757959537090045, 3.654152885361008796, 3.449278298560964462, 3.320244733839166074,
      3.224575052047029100, 3.147889289517149969, 3.083526132001233044, 3.027837791768635434,
@@ -79,6 +80,7 @@ pub static ZIG_NORM_X: [f64; 257] =
      0.487443966121754335, 0.463634336771763245, 0.437518402186662658, 0.408389134588000746,
      0.375121332850465727, 0.335737519180459465, 0.286174591747260509, 0.215241895913273806,
      0.000000000000000000];
+#[rustfmt_skip]
 pub static ZIG_NORM_F: [f64; 257] =
     [0.000477467764586655, 0.001260285930498598, 0.002609072746106363, 0.004037972593371872,
      0.005522403299264754, 0.007050875471392110, 0.008616582769422917, 0.010214971439731100,
@@ -146,6 +148,7 @@ pub static ZIG_NORM_F: [f64; 257] =
      0.932060075968990209, 0.945198953453078028, 0.959879091812415930, 0.977101701282731328,
      1.000000000000000000];
 pub const ZIG_EXP_R: f64 = 7.697117470131050077;
+#[rustfmt_skip]
 pub static ZIG_EXP_X: [f64; 257] =
     [8.697117470131052741, 7.697117470131050077, 6.941033629377212577, 6.478378493832569696,
      6.144164665772472667, 5.882144315795399869, 5.666410167454033697, 5.482890627526062488,
@@ -212,6 +215,7 @@ pub static ZIG_EXP_X: [f64; 257] =
      0.253658363385912022, 0.233790483059674731, 0.212671510630966620, 0.189958689622431842,
      0.165127622564187282, 0.137304980940012589, 0.104838507565818778, 0.063852163815001570,
      0.000000000000000000];
+#[rustfmt_skip]
 pub static ZIG_EXP_F: [f64; 257] =
     [0.000167066692307963, 0.000454134353841497, 0.000967269282327174, 0.001536299780301573,
      0.002145967743718907, 0.002788798793574076, 0.003460264777836904, 0.004157295120833797,
index f51483cc11f464b7b732f19fb19b191bf17da518..ac2b9b07ffd13ceb4f995ce25ec24f8f1e424f48 100644 (file)
@@ -48,7 +48,9 @@ static EMPTY: IsaacRng = IsaacRng {
     cnt: 0,
     rsl: [w(0); RAND_SIZE_USIZE],
     mem: [w(0); RAND_SIZE_USIZE],
-    a: w(0), b: w(0), c: w(0),
+    a: w(0),
+    b: w(0),
+    c: w(0),
 };
 
 impl IsaacRng {
@@ -95,15 +97,23 @@ impl IsaacRng {
             macro_rules! memloop {
                 ($arr:expr) => {{
                     for i in (0..RAND_SIZE_USIZE).step_by(8) {
-                        a=a+$arr[i  ]; b=b+$arr[i+1];
-                        c=c+$arr[i+2]; d=d+$arr[i+3];
-                        e=e+$arr[i+4]; f=f+$arr[i+5];
-                        g=g+$arr[i+6]; h=h+$arr[i+7];
+                        a = a + $arr[i];
+                        b = b + $arr[i + 1];
+                        c = c + $arr[i + 2];
+                        d = d + $arr[i + 3];
+                        e = e + $arr[i + 4];
+                        f = f + $arr[i + 5];
+                        g = g + $arr[i + 6];
+                        h = h + $arr[i + 7];
                         mix!();
-                        self.mem[i  ]=a; self.mem[i+1]=b;
-                        self.mem[i+2]=c; self.mem[i+3]=d;
-                        self.mem[i+4]=e; self.mem[i+5]=f;
-                        self.mem[i+6]=g; self.mem[i+7]=h;
+                        self.mem[i] = a;
+                        self.mem[i + 1] = b;
+                        self.mem[i + 2] = c;
+                        self.mem[i + 3] = d;
+                        self.mem[i + 4] = e;
+                        self.mem[i + 5] = f;
+                        self.mem[i + 6] = g;
+                        self.mem[i + 7] = h;
                     }
                 }}
             }
@@ -113,10 +123,14 @@ impl IsaacRng {
         } else {
             for i in (0..RAND_SIZE_USIZE).step_by(8) {
                 mix!();
-                self.mem[i  ]=a; self.mem[i+1]=b;
-                self.mem[i+2]=c; self.mem[i+3]=d;
-                self.mem[i+4]=e; self.mem[i+5]=f;
-                self.mem[i+6]=g; self.mem[i+7]=h;
+                self.mem[i] = a;
+                self.mem[i + 1] = b;
+                self.mem[i + 2] = c;
+                self.mem[i + 3] = d;
+                self.mem[i + 4] = e;
+                self.mem[i + 5] = f;
+                self.mem[i + 6] = g;
+                self.mem[i + 7] = h;
             }
         }
 
@@ -290,7 +304,9 @@ static EMPTY_64: Isaac64Rng = Isaac64Rng {
     cnt: 0,
     rsl: [w(0); RAND_SIZE_64],
     mem: [w(0); RAND_SIZE_64],
-    a: w(0), b: w(0), c: w(0),
+    a: w(0),
+    b: w(0),
+    c: w(0),
 };
 
 impl Isaac64Rng {
@@ -311,8 +327,14 @@ impl Isaac64Rng {
                 let mut $var = w(0x9e3779b97f4a7c13);
             )
         }
-        init!(a); init!(b); init!(c); init!(d);
-        init!(e); init!(f); init!(g); init!(h);
+        init!(a);
+        init!(b);
+        init!(c);
+        init!(d);
+        init!(e);
+        init!(f);
+        init!(g);
+        init!(h);
 
         macro_rules! mix {
             () => {{
@@ -335,15 +357,23 @@ impl Isaac64Rng {
             macro_rules! memloop {
                 ($arr:expr) => {{
                     for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) {
-                        a=a+$arr[i  ]; b=b+$arr[i+1];
-                        c=c+$arr[i+2]; d=d+$arr[i+3];
-                        e=e+$arr[i+4]; f=f+$arr[i+5];
-                        g=g+$arr[i+6]; h=h+$arr[i+7];
+                        a = a + $arr[i];
+                        b = b + $arr[i + 1];
+                        c = c + $arr[i + 2];
+                        d = d + $arr[i + 3];
+                        e = e + $arr[i + 4];
+                        f = f + $arr[i + 5];
+                        g = g + $arr[i + 6];
+                        h = h + $arr[i + 7];
                         mix!();
-                        self.mem[i  ]=a; self.mem[i+1]=b;
-                        self.mem[i+2]=c; self.mem[i+3]=d;
-                        self.mem[i+4]=e; self.mem[i+5]=f;
-                        self.mem[i+6]=g; self.mem[i+7]=h;
+                        self.mem[i] = a;
+                        self.mem[i + 1] = b;
+                        self.mem[i + 2] = c;
+                        self.mem[i + 3] = d;
+                        self.mem[i + 4] = e;
+                        self.mem[i + 5] = f;
+                        self.mem[i + 6] = g;
+                        self.mem[i + 7] = h;
                     }
                 }}
             }
@@ -353,10 +383,14 @@ impl Isaac64Rng {
         } else {
             for i in (0..RAND_SIZE_64 / 8).map(|i| i * 8) {
                 mix!();
-                self.mem[i  ]=a; self.mem[i+1]=b;
-                self.mem[i+2]=c; self.mem[i+3]=d;
-                self.mem[i+4]=e; self.mem[i+5]=f;
-                self.mem[i+6]=g; self.mem[i+7]=h;
+                self.mem[i] = a;
+                self.mem[i + 1] = b;
+                self.mem[i + 2] = c;
+                self.mem[i + 3] = d;
+                self.mem[i + 4] = e;
+                self.mem[i + 5] = f;
+                self.mem[i + 6] = g;
+                self.mem[i + 7] = h;
             }
         }
 
@@ -370,7 +404,7 @@ impl Isaac64Rng {
         let mut a = self.a;
         let mut b = self.b + self.c;
         const MIDPOINT: usize =  RAND_SIZE_64 / 2;
-        const MP_VEC: [(usize, usize); 2] = [(0,MIDPOINT), (MIDPOINT, 0)];
+        const MP_VEC: [(usize, usize); 2] = [(0, MIDPOINT), (MIDPOINT, 0)];
         macro_rules! ind {
             ($x:expr) => {
                 *self.mem.get_unchecked((($x >> 3).0 as usize) & (RAND_SIZE_64 - 1))
@@ -573,6 +607,7 @@ mod tests {
     }
 
     #[test]
+    #[rustfmt_skip]
     fn test_rng_32_true_values() {
         let seed: &[_] = &[1, 23, 456, 7890, 12345];
         let mut ra: IsaacRng = SeedableRng::from_seed(seed);
@@ -585,7 +620,9 @@ mod tests {
         let seed: &[_] = &[12345, 67890, 54321, 9876];
         let mut rb: IsaacRng = SeedableRng::from_seed(seed);
         // skip forward to the 10000th number
-        for _ in 0..10000 { rb.next_u32(); }
+        for _ in 0..10000 {
+            rb.next_u32();
+        }
 
         let v = (0..10).map(|_| rb.next_u32()).collect::<Vec<_>>();
         assert_eq!(v,
@@ -593,6 +630,7 @@ mod tests {
                         1576568959, 3507990155, 179069555, 141456972, 2478885421));
     }
     #[test]
+    #[rustfmt_skip]
     fn test_rng_64_true_values() {
         let seed: &[_] = &[1, 23, 456, 7890, 12345];
         let mut ra: Isaac64Rng = SeedableRng::from_seed(seed);
@@ -607,7 +645,9 @@ mod tests {
         let seed: &[_] = &[12345, 67890, 54321, 9876];
         let mut rb: Isaac64Rng = SeedableRng::from_seed(seed);
         // skip forward to the 10000th number
-        for _ in 0..10000 { rb.next_u64(); }
+        for _ in 0..10000 {
+            rb.next_u64();
+        }
 
         let v = (0..10).map(|_| rb.next_u64()).collect::<Vec<_>>();
         assert_eq!(v,
@@ -615,6 +655,7 @@ mod tests {
                         17196852593171130876, 2606123525235546165, 15790932315217671084,
                         596345674630742204, 9947027391921273664, 11788097613744130851,
                         10391409374914919106));
+
     }
 
     #[test]
index c3dace513112fa48de18e8bcb900a85a4fce4472..b5a1eb9520cec6eb1983925f9ac4c40b6b3674cb 100644 (file)
 #![feature(num_bits_bytes)]
 #![feature(staged_api)]
 #![feature(step_by)]
+#![feature(custom_attribute)]
+#![allow(unused_attributes)]
 
-#![cfg_attr(test, feature(test, rand, rustc_private, iter_order))]
+#![cfg_attr(test, feature(test, rand, rustc_private, iter_order_deprecated))]
 
 #![allow(deprecated)]
 
-#[cfg(test)] #[macro_use] extern crate std;
-#[cfg(test)] #[macro_use] extern crate log;
+#[cfg(test)]
+#[macro_use]
+extern crate std;
+#[cfg(test)]
+#[macro_use]
+extern crate log;
 
 use core::f64;
 use core::intrinsics;
@@ -217,7 +223,10 @@ pub trait Rng : Sized {
     /// Return an iterator that will yield an infinite number of randomly
     /// generated items.
     fn gen_iter<'a, T: Rand>(&'a mut self) -> Generator<'a, T, Self> {
-        Generator { rng: self, _marker: PhantomData }
+        Generator {
+            rng: self,
+            _marker: PhantomData,
+        }
     }
 
     /// Generate a random value in the range [`low`, `high`).
@@ -272,9 +281,9 @@ pub trait Rng : Sized {
 /// Iterator which will generate a stream of random items.
 ///
 /// This iterator is created via the `gen_iter` method on `Rng`.
-pub struct Generator<'a, T, R:'a> {
+pub struct Generator<'a, T, R: 'a> {
     rng: &'a mut R,
-    _marker: PhantomData<T>
+    _marker: PhantomData<T>,
 }
 
 impl<'a, T: Rand, R: Rng> Iterator for Generator<'a, T, R> {
@@ -288,7 +297,7 @@ impl<'a, T: Rand, R: Rng> Iterator for Generator<'a, T, R> {
 /// Iterator which will continuously generate random ascii characters.
 ///
 /// This iterator is created via the `gen_ascii_chars` method on `Rng`.
-pub struct AsciiGenerator<'a, R:'a> {
+pub struct AsciiGenerator<'a, R: 'a> {
     rng: &'a mut R,
 }
 
@@ -384,7 +393,7 @@ impl SeedableRng<[u32; 4]> for XorShiftRng {
             x: seed[0],
             y: seed[1],
             z: seed[2],
-            w: seed[3]
+            w: seed[3],
         }
     }
 }
@@ -396,7 +405,12 @@ impl Rand for XorShiftRng {
             tuple = rng.gen();
         }
         let (x, y, z, w) = tuple;
-        XorShiftRng { x: x, y: y, z: z, w: w }
+        XorShiftRng {
+            x: x,
+            y: y,
+            z: z,
+            w: w,
+        }
     }
 }
 
@@ -420,7 +434,9 @@ pub struct Closed01<F>(pub F);
 mod test {
     use std::__rand as rand;
 
-    pub struct MyRng<R> { inner: R }
+    pub struct MyRng<R> {
+        inner: R,
+    }
 
     impl<R: rand::Rng> ::Rng for MyRng<R> {
         fn next_u32(&mut self) -> u32 {
index 04093db4b6ff79fd2b0eda113c744f3729e94481..726a4554626f538345581d95b87315f860931587 100644 (file)
@@ -14,7 +14,7 @@ use core::char;
 use core::isize;
 use core::usize;
 
-use {Rand,Rng};
+use {Rand, Rng};
 
 impl Rand for isize {
     #[inline]
@@ -185,7 +185,9 @@ macro_rules! tuple_impl {
 
 impl Rand for () {
     #[inline]
-    fn rand<R: Rng>(_: &mut R) -> () { () }
+    fn rand<R: Rng>(_: &mut R) -> () {
+        ()
+    }
 }
 tuple_impl!{A}
 tuple_impl!{A, B}
index 99fe2bb5ab507f530f2eb1f8ae0d6082ab5e5f97..584cf78a1cdbfc9c2c4d9c83b8096276a022f43d 100644 (file)
@@ -35,12 +35,12 @@ impl<R: Rng, Rsdr: Reseeder<R>> ReseedingRng<R, Rsdr> {
     /// * `rng`: the random number generator to use.
     /// * `generation_threshold`: the number of bytes of entropy at which to reseed the RNG.
     /// * `reseeder`: the reseeding object to use.
-    pub fn new(rng: R, generation_threshold: usize, reseeder: Rsdr) -> ReseedingRng<R,Rsdr> {
+    pub fn new(rng: R, generation_threshold: usize, reseeder: Rsdr) -> ReseedingRng<R, Rsdr> {
         ReseedingRng {
             rng: rng,
             generation_threshold: generation_threshold,
             bytes_generated: 0,
-            reseeder: reseeder
+            reseeder: reseeder,
         }
     }
 
@@ -90,7 +90,7 @@ impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R> + Default>
             rng: SeedableRng::from_seed(seed),
             generation_threshold: DEFAULT_GENERATION_THRESHOLD,
             bytes_generated: 0,
-            reseeder: rsdr
+            reseeder: rsdr,
         }
     }
 }
@@ -114,19 +114,21 @@ impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Default for ReseedWithDefault {
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn default() -> ReseedWithDefault { ReseedWithDefault }
+    fn default() -> ReseedWithDefault {
+        ReseedWithDefault
+    }
 }
 
 #[cfg(test)]
 mod tests {
     use std::prelude::v1::*;
 
-    use core::iter::{order, repeat};
+    use core::iter::order;
     use super::{ReseedingRng, ReseedWithDefault};
     use {SeedableRng, Rng};
 
     struct Counter {
-        i: u32
+        i: u32,
     }
 
     impl Rng for Counter {
@@ -153,7 +155,7 @@ mod tests {
 
     #[test]
     fn test_reseeding() {
-        let mut rs = ReseedingRng::new(Counter {i:0}, 400, ReseedWithDefault);
+        let mut rs = ReseedingRng::new(Counter { i: 0 }, 400, ReseedWithDefault);
 
         let mut i = 0;
         for _ in 0..1000 {
index af36d45ab573d181f9e7c3360a70ea4412362d0c..1c6cb06d54ae4218530c3b3e22df155c442c83a6 100644 (file)
@@ -467,37 +467,44 @@ pub mod reader {
         f(&d.data[d.start..d.end])
     }
 
-
     pub fn doc_as_u8(d: Doc) -> u8 {
         assert_eq!(d.end, d.start + 1);
         d.data[d.start]
     }
 
-    pub fn doc_as_u16(d: Doc) -> u16 {
-        assert_eq!(d.end, d.start + 2);
-        let mut b = [0; 2];
-        bytes::copy_memory(&d.data[d.start..d.end], &mut b);
-        unsafe { (*(b.as_ptr() as *const u16)).to_be() }
-    }
-
-    pub fn doc_as_u32(d: Doc) -> u32 {
-        assert_eq!(d.end, d.start + 4);
-        let mut b = [0; 4];
-        bytes::copy_memory(&d.data[d.start..d.end], &mut b);
-        unsafe { (*(b.as_ptr() as *const u32)).to_be() }
-    }
-
     pub fn doc_as_u64(d: Doc) -> u64 {
-        assert_eq!(d.end, d.start + 8);
-        let mut b = [0; 8];
-        bytes::copy_memory(&d.data[d.start..d.end], &mut b);
-        unsafe { (*(b.as_ptr() as *const u64)).to_be() }
+        if d.end >= 8 {
+            // For performance, we read 8 big-endian bytes,
+            // and mask off the junk if there is any. This
+            // obviously won't work on the first 8 bytes
+            // of a file - we will fall of the start
+            // of the page and segfault.
+
+            let mut b = [0; 8];
+            bytes::copy_memory(&d.data[d.end-8..d.end], &mut b);
+            let data = unsafe { (*(b.as_ptr() as *const u64)).to_be() };
+            let len = d.end - d.start;
+            if len < 8 {
+                data & ((1<<(len*8))-1)
+            } else {
+                data
+            }
+        } else {
+            let mut result = 0;
+            for b in &d.data[d.start..d.end] {
+                result = (result<<8) + (*b as u64);
+            }
+            result
+        }
     }
 
-    pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 }
-    pub fn doc_as_i16(d: Doc) -> i16 { doc_as_u16(d) as i16 }
-    pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 }
-    pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 }
+    #[inline] pub fn doc_as_u16(d: Doc) -> u16 { doc_as_u64(d) as u16 }
+    #[inline] pub fn doc_as_u32(d: Doc) -> u32 { doc_as_u64(d) as u32 }
+
+    #[inline] pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 }
+    #[inline] pub fn doc_as_i16(d: Doc) -> i16 { doc_as_u16(d) as i16 }
+    #[inline] pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 }
+    #[inline] pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 }
 
     pub struct Decoder<'a> {
         parent: Doc<'a>,
@@ -907,7 +914,7 @@ pub mod writer {
         }
     }
 
-    fn write_vuint<W: Write>(w: &mut W, n: usize) -> EncodeResult {
+    pub fn write_vuint<W: Write>(w: &mut W, n: usize) -> EncodeResult {
         if n < 0x7f { return write_sized_vuint(w, n, 1); }
         if n < 0x4000 { return write_sized_vuint(w, n, 2); }
         if n < 0x200000 { return write_sized_vuint(w, n, 3); }
@@ -925,15 +932,6 @@ pub mod writer {
             }
         }
 
-        /// FIXME(pcwalton): Workaround for badness in trans. DO NOT USE ME.
-        pub unsafe fn unsafe_clone(&self) -> Encoder<'a> {
-            Encoder {
-                writer: mem::transmute_copy(&self.writer),
-                size_positions: self.size_positions.clone(),
-                relax_limit: self.relax_limit,
-            }
-        }
-
         pub fn start_tag(&mut self, tag_id: usize) -> EncodeResult {
             debug!("Start tag {:?}", tag_id);
             assert!(tag_id >= NUM_IMPLICIT_TAGS);
@@ -996,35 +994,43 @@ pub mod writer {
 
         pub fn wr_tagged_u64(&mut self, tag_id: usize, v: u64) -> EncodeResult {
             let bytes: [u8; 8] = unsafe { mem::transmute(v.to_be()) };
-            self.wr_tagged_bytes(tag_id, &bytes)
+            // tagged integers are emitted in big-endian, with no
+            // leading zeros.
+            let leading_zero_bytes = v.leading_zeros()/8;
+            self.wr_tagged_bytes(tag_id, &bytes[leading_zero_bytes as usize..])
         }
 
-        pub fn wr_tagged_u32(&mut self, tag_id: usize, v: u32)  -> EncodeResult{
-            let bytes: [u8; 4] = unsafe { mem::transmute(v.to_be()) };
-            self.wr_tagged_bytes(tag_id, &bytes)
+        #[inline]
+        pub fn wr_tagged_u32(&mut self, tag_id: usize, v: u32)  -> EncodeResult {
+            self.wr_tagged_u64(tag_id, v as u64)
         }
 
+        #[inline]
         pub fn wr_tagged_u16(&mut self, tag_id: usize, v: u16) -> EncodeResult {
-            let bytes: [u8; 2] = unsafe { mem::transmute(v.to_be()) };
-            self.wr_tagged_bytes(tag_id, &bytes)
+            self.wr_tagged_u64(tag_id, v as u64)
         }
 
+        #[inline]
         pub fn wr_tagged_u8(&mut self, tag_id: usize, v: u8) -> EncodeResult {
             self.wr_tagged_bytes(tag_id, &[v])
         }
 
+        #[inline]
         pub fn wr_tagged_i64(&mut self, tag_id: usize, v: i64) -> EncodeResult {
             self.wr_tagged_u64(tag_id, v as u64)
         }
 
+        #[inline]
         pub fn wr_tagged_i32(&mut self, tag_id: usize, v: i32) -> EncodeResult {
             self.wr_tagged_u32(tag_id, v as u32)
         }
 
+        #[inline]
         pub fn wr_tagged_i16(&mut self, tag_id: usize, v: i16) -> EncodeResult {
             self.wr_tagged_u16(tag_id, v as u16)
         }
 
+        #[inline]
         pub fn wr_tagged_i8(&mut self, tag_id: usize, v: i8) -> EncodeResult {
             self.wr_tagged_bytes(tag_id, &[v as u8])
         }
index 9616b596c063827512e49afeabb8ff57239df46e..7cb2de78e2c7dbdf1248b05ed9270c458ff90e13 100644 (file)
@@ -298,10 +298,18 @@ const FOO: i32 = { 0 }; // but brackets are useless here
 ```
 "##,
 
+// FIXME(#24111) Change the language here when const fn stabilizes
 E0015: r##"
 The only functions that can be called in static or constant expressions are
-`const` functions. Rust currently does not support more general compile-time
-function execution.
+`const` functions, and struct/enum constructors. `const` functions are only
+available on a nightly compiler. Rust currently does not support more general
+compile-time function execution.
+
+```
+const FOO: Option<u8> = Some(1); // enum constructor
+struct Bar {x: u8}
+const BAR: Bar = Bar {x: 1}; // struct constructor
+```
 
 See [RFC 911] for more details on the design of `const fn`s.
 
@@ -1886,7 +1894,150 @@ This explicitly states that you expect the trait object `SomeTrait` to
 contain references (with a maximum lifetime of `'a`).
 
 [1]: https://github.com/rust-lang/rfcs/pull/1156
-"##
+"##,
+
+E0454: r##"
+A link name was given with an empty name. Erroneous code example:
+
+```
+#[link(name = "")] extern {} // error: #[link(name = "")] given with empty name
+```
+
+The rust compiler cannot link to an external library if you don't give it its
+name. Example:
+
+```
+#[link(name = "some_lib")] extern {} // ok!
+```
+"##,
+
+E0458: r##"
+An unknown "kind" was specified for a link attribute. Erroneous code example:
+
+```
+#[link(kind = "wonderful_unicorn")] extern {}
+// error: unknown kind: `wonderful_unicorn`
+```
+
+Please specify a valid "kind" value, from one of the following:
+ * static
+ * dylib
+ * framework
+"##,
+
+E0459: r##"
+A link was used without a name parameter. Erroneous code example:
+
+```
+#[link(kind = "dylib")] extern {}
+// error: #[link(...)] specified without `name = "foo"`
+```
+
+Please add the name parameter to allow the rust compiler to find the library
+you want. Example:
+
+```
+#[link(kind = "dylib", name = "some_lib")] extern {} // ok!
+```
+"##,
+
+E0493: r##"
+A type with a destructor was assigned to an invalid type of variable. Erroneous
+code example:
+
+```
+struct Foo {
+    a: u32
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {}
+}
+
+const F : Foo = Foo { a : 0 };
+// error: constants are not allowed to have destructors
+static S : Foo = Foo { a : 0 };
+// error: statics are not allowed to have destructors
+```
+
+To solve this issue, please use a type which does allow the usage of type with
+destructors.
+"##,
+
+E0494: r##"
+A reference of an interior static was assigned to another const/static.
+Erroneous code example:
+
+```
+struct Foo {
+    a: u32
+}
+
+static S : Foo = Foo { a : 0 };
+static A : &'static u32 = &S.a;
+// error: cannot refer to the interior of another static, use a
+//        constant instead
+```
+
+The "base" variable has to be a const if you want another static/const variable
+to refer to one of its fields. Example:
+
+```
+struct Foo {
+    a: u32
+}
+
+const S : Foo = Foo { a : 0 };
+static A : &'static u32 = &S.a; // ok!
+```
+"##,
+
+E0496: r##"
+A lifetime name is shadowing another lifetime name. Erroneous code example:
+
+```
+struct Foo<'a> {
+    a: &'a i32,
+}
+
+impl<'a> Foo<'a> {
+    fn f<'a>(x: &'a i32) { // error: lifetime name `'a` shadows a lifetime
+                           //        name that is already in scope
+    }
+}
+```
+
+Please change the name of one of the lifetimes to remove this error. Example:
+
+
+```
+struct Foo<'a> {
+    a: &'a i32,
+}
+
+impl<'a> Foo<'a> {
+    fn f<'b>(x: &'b i32) { // ok!
+    }
+}
+
+fn main() {
+}
+```
+"##,
+
+E0497: r##"
+A stability attribute was used outside of the standard library. Erroneous code
+example:
+
+```
+#[stable] // error: stability attributes may not be used outside of the
+          //        standard library
+fn foo() {}
+```
+
+It is not possible to use stability attributes outside of the standard library.
+Also, for now, it is not possible to write deprecation messages either.
+"##,
 
 }
 
@@ -1914,5 +2065,46 @@ register_diagnostics! {
     E0314, // closure outlives stack frame
     E0315, // cannot invoke closure outside of its lifetime
     E0316, // nested quantification of lifetimes
-    E0400  // overloaded derefs are not allowed in constants
+    E0400, // overloaded derefs are not allowed in constants
+    E0452, // malformed lint attribute
+    E0453, // overruled by outer forbid
+    E0455, // native frameworks are only available on OSX targets
+    E0456, // plugin `..` is not available for triple `..`
+    E0457, // plugin `..` only found in rlib format, but must be available...
+    E0460, // found possibly newer version of crate `..`
+    E0461, // couldn't find crate `..` with expected target triple ..
+    E0462, // found staticlib `..` instead of rlib or dylib
+    E0463, // can't find crate for `..`
+    E0464, // multiple matching crates for `..`
+    E0465, // multiple .. candidates for `..` found
+    E0466, // bad macro import
+    E0467, // bad macro reexport
+    E0468, // an `extern crate` loading macros must be at the crate root
+    E0469, // imported macro not found
+    E0470, // reexported macro not found
+    E0471, // constant evaluation error: ..
+    E0472, // asm! is unsupported on this target
+    E0473, // dereference of reference outside its lifetime
+    E0474, // captured variable `..` does not outlive the enclosing closure
+    E0475, // index of slice outside its lifetime
+    E0476, // lifetime of the source pointer does not outlive lifetime bound...
+    E0477, // the type `..` does not fulfill the required lifetime...
+    E0478, // lifetime bound not satisfied
+    E0479, // the type `..` (provided as the value of a type parameter) is...
+    E0480, // lifetime of method receiver does not outlive the method call
+    E0481, // lifetime of function argument does not outlive the function call
+    E0482, // lifetime of return value does not outlive the function call
+    E0483, // lifetime of operand does not outlive the operation
+    E0484, // reference is not valid at the time of borrow
+    E0485, // automatically reference is not valid at the time of borrow
+    E0486, // type of expression contains references that are not valid during...
+    E0487, // unsafe use of destructor: destructor might be called while...
+    E0488, // lifetime of variable does not enclose its declaration
+    E0489, // type/lifetime parameter not in scope here
+    E0490, // a value of type `..` is borrowed for too long
+    E0491, // in type `..`, reference has a longer lifetime than the data it...
+    E0492, // cannot borrow a constant which contains interior mutability
+    E0495, // cannot infer an appropriate lifetime due to conflicting requirements
+    E0498, // malformed plugin attribute
+    E0514, // metadata version mismatch
 }
diff --git a/src/librustc/front/check_attr.rs b/src/librustc/front/check_attr.rs
new file mode 100644 (file)
index 0000000..cca14f1
--- /dev/null
@@ -0,0 +1,110 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use session::Session;
+
+use syntax::ast;
+use syntax::attr::AttrMetaMethods;
+use syntax::visit;
+use syntax::visit::Visitor;
+
+#[derive(Copy, Clone, PartialEq)]
+enum Target {
+    Fn,
+    Struct,
+    Enum,
+    Other,
+}
+
+impl Target {
+    fn from_item(item: &ast::Item) -> Target {
+        match item.node {
+            ast::ItemFn(..) => Target::Fn,
+            ast::ItemStruct(..) => Target::Struct,
+            ast::ItemEnum(..) => Target::Enum,
+            _ => Target::Other,
+        }
+    }
+}
+
+struct CheckAttrVisitor<'a> {
+    sess: &'a Session,
+}
+
+impl<'a> CheckAttrVisitor<'a> {
+    fn check_inline(&self, attr: &ast::Attribute, target: Target) {
+        if target != Target::Fn {
+            self.sess.span_err(
+                attr.span,
+                "attribute should be applied to function");
+        }
+    }
+
+    fn check_repr(&self, attr: &ast::Attribute, target: Target) {
+        let words = match attr.meta_item_list() {
+            Some(words) => words,
+            None => {
+                return;
+            }
+        };
+        for word in words {
+            let word: &str = &word.name();
+            match word {
+                "C" => {
+                    if target != Target::Struct && target != Target::Enum {
+                        self.sess.span_err(
+                            attr.span,
+                            "attribute should be applied to struct or enum");
+                    }
+                }
+                "packed" |
+                "simd" => {
+                    if target != Target::Struct {
+                        self.sess.span_err(
+                            attr.span,
+                            "attribute should be applied to struct");
+                    }
+                }
+                "i8" | "u8" | "i16" | "u16" |
+                "i32" | "u32" | "i64" | "u64" |
+                "isize" | "usize" => {
+                    if target != Target::Enum {
+                        self.sess.span_err(
+                            attr.span,
+                            "attribute should be applied to enum");
+                    }
+                }
+                _ => (),
+            }
+        }
+    }
+
+    fn check_attribute(&self, attr: &ast::Attribute, target: Target) {
+        let name: &str = &attr.name();
+        match name {
+            "inline" => self.check_inline(attr, target),
+            "repr" => self.check_repr(attr, target),
+            _ => (),
+        }
+    }
+}
+
+impl<'a, 'v> Visitor<'v> for CheckAttrVisitor<'a> {
+    fn visit_item(&mut self, item: &ast::Item) {
+        let target = Target::from_item(item);
+        for attr in &item.attrs {
+            self.check_attribute(attr, target);
+        }
+    }
+}
+
+pub fn check_crate(sess: &Session, krate: &ast::Crate) {
+    visit::walk_crate(&mut CheckAttrVisitor { sess: sess }, krate);
+}
index 4e16d9e5670895678a4b3857d712a8c98cae44f7..7d4809d457c80c37e9739f38e8a3db2a066fd6d9 100644 (file)
@@ -26,7 +26,7 @@ pub use self::Code::*;
 use front::map::{self, Node};
 use syntax::abi;
 use rustc_front::hir::{Block, FnDecl};
-use syntax::ast::{NodeId, Ident};
+use syntax::ast::{Name, NodeId};
 use rustc_front::hir as ast;
 use syntax::codemap::Span;
 use rustc_front::visit::FnKind;
@@ -107,7 +107,7 @@ impl<'a> Code<'a> {
 /// These are all the components one can extract from a fn item for
 /// use when implementing FnLikeNode operations.
 struct ItemFnParts<'a> {
-    ident:    Ident,
+    name:     Name,
     decl:     &'a ast::FnDecl,
     unsafety: ast::Unsafety,
     constness: ast::Constness,
@@ -189,13 +189,13 @@ impl<'a> FnLikeNode<'a> {
 
     pub fn kind(self) -> FnKind<'a> {
         let item = |p: ItemFnParts<'a>| -> FnKind<'a> {
-            FnKind::ItemFn(p.ident, p.generics, p.unsafety, p.constness, p.abi, p.vis)
+            FnKind::ItemFn(p.name, p.generics, p.unsafety, p.constness, p.abi, p.vis)
         };
         let closure = |_: ClosureParts| {
             FnKind::Closure
         };
-        let method = |_, ident, sig: &'a ast::MethodSig, vis, _, _| {
-            FnKind::Method(ident, sig, vis)
+        let method = |_, name: Name, sig: &'a ast::MethodSig, vis, _, _| {
+            FnKind::Method(name, sig, vis)
         };
         self.handle(item, method, closure)
     }
@@ -203,7 +203,7 @@ impl<'a> FnLikeNode<'a> {
     fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A where
         I: FnOnce(ItemFnParts<'a>) -> A,
         M: FnOnce(NodeId,
-                  Ident,
+                  Name,
                   &'a ast::MethodSig,
                   Option<ast::Visibility>,
                   &'a ast::Block,
@@ -216,7 +216,7 @@ impl<'a> FnLikeNode<'a> {
                 ast::ItemFn(ref decl, unsafety, constness, abi, ref generics, ref block) =>
                     item_fn(ItemFnParts {
                         id: i.id,
-                        ident: i.ident,
+                        name: i.name,
                         decl: &**decl,
                         unsafety: unsafety,
                         body: &**block,
@@ -230,14 +230,14 @@ impl<'a> FnLikeNode<'a> {
             },
             map::NodeTraitItem(ti) => match ti.node {
                 ast::MethodTraitItem(ref sig, Some(ref body)) => {
-                    method(ti.id, ti.ident, sig, None, body, ti.span)
+                    method(ti.id, ti.name, sig, None, body, ti.span)
                 }
                 _ => panic!("trait method FnLikeNode that is not fn-like"),
             },
             map::NodeImplItem(ii) => {
                 match ii.node {
                     ast::MethodImplItem(ref sig, ref body) => {
-                        method(ii.id, ii.ident, sig, Some(ii.vis), body, ii.span)
+                        method(ii.id, ii.name, sig, Some(ii.vis), body, ii.span)
                     }
                     _ => {
                         panic!("impl method FnLikeNode that is not fn-like")
diff --git a/src/librustc/front/map/collector.rs b/src/librustc/front/map/collector.rs
new file mode 100644 (file)
index 0000000..f255949
--- /dev/null
@@ -0,0 +1,316 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::*;
+use super::MapEntry::*;
+
+use rustc_front::hir::*;
+use rustc_front::util;
+use rustc_front::visit::{self, Visitor};
+use middle::def_id::{CRATE_DEF_INDEX, DefIndex};
+use std::iter::repeat;
+use syntax::ast::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
+use syntax::codemap::Span;
+
+/// A Visitor that walks over an AST and collects Node's into an AST
+/// Map.
+pub struct NodeCollector<'ast> {
+    pub map: Vec<MapEntry<'ast>>,
+    pub definitions: Definitions,
+    pub parent_node: NodeId,
+}
+
+impl<'ast> NodeCollector<'ast> {
+    pub fn root() -> NodeCollector<'ast> {
+        let mut collector = NodeCollector {
+            map: vec![],
+            definitions: Definitions::new(),
+            parent_node: CRATE_NODE_ID,
+        };
+        collector.insert_entry(CRATE_NODE_ID, RootCrate);
+
+        let result = collector.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot);
+        assert_eq!(result, CRATE_DEF_INDEX);
+
+        collector.create_def_with_parent(Some(CRATE_DEF_INDEX), DUMMY_NODE_ID, DefPathData::Misc);
+
+        collector
+    }
+
+    pub fn extend(parent: &'ast InlinedParent,
+                  parent_node: NodeId,
+                  parent_def_path: DefPath,
+                  map: Vec<MapEntry<'ast>>,
+                  definitions: Definitions)
+                  -> NodeCollector<'ast> {
+        let mut collector = NodeCollector {
+            map: map,
+            parent_node: parent_node,
+            definitions: definitions,
+        };
+
+        collector.insert_entry(parent_node, RootInlinedParent(parent));
+        collector.create_def(parent_node, DefPathData::InlinedRoot(parent_def_path));
+
+        collector
+    }
+
+    fn parent_def(&self) -> Option<DefIndex> {
+        let mut parent_node = Some(self.parent_node);
+        while let Some(p) = parent_node {
+            if let Some(q) = self.definitions.opt_def_index(p) {
+                return Some(q);
+            }
+            parent_node = self.map[p as usize].parent_node();
+        }
+        None
+    }
+
+    fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex {
+        let parent_def = self.parent_def();
+        self.definitions.create_def_with_parent(parent_def, node_id, data)
+    }
+
+    fn create_def_with_parent(&mut self,
+                              parent: Option<DefIndex>,
+                              node_id: NodeId,
+                              data: DefPathData)
+                              -> DefIndex {
+        self.definitions.create_def_with_parent(parent, node_id, data)
+    }
+
+    fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) {
+        debug!("ast_map: {:?} => {:?}", id, entry);
+        let len = self.map.len();
+        if id as usize >= len {
+            self.map.extend(repeat(NotPresent).take(id as usize - len + 1));
+        }
+        self.map[id as usize] = entry;
+    }
+
+    fn insert_def(&mut self, id: NodeId, node: Node<'ast>, data: DefPathData) -> DefIndex {
+        self.insert(id, node);
+        self.create_def(id, data)
+    }
+
+    fn insert(&mut self, id: NodeId, node: Node<'ast>) {
+        let entry = MapEntry::from_node(self.parent_node, node);
+        self.insert_entry(id, entry);
+    }
+}
+
+impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
+    fn visit_item(&mut self, i: &'ast Item) {
+        // Pick the def data. This need not be unique, but the more
+        // information we encapsulate into
+        let def_data = match i.node {
+            ItemDefaultImpl(..) | ItemImpl(..) => DefPathData::Impl,
+            ItemEnum(..) | ItemStruct(..) | ItemTrait(..) => DefPathData::Type(i.name),
+            ItemExternCrate(..) | ItemMod(..) => DefPathData::Mod(i.name),
+            ItemStatic(..) | ItemConst(..) | ItemFn(..) => DefPathData::Value(i.name),
+            _ => DefPathData::Misc,
+        };
+
+        self.insert_def(i.id, NodeItem(i), def_data);
+
+        let parent_node = self.parent_node;
+        self.parent_node = i.id;
+
+        match i.node {
+            ItemImpl(..) => {}
+            ItemEnum(ref enum_definition, _) => {
+                for v in &enum_definition.variants {
+                    let variant_def_index =
+                        self.insert_def(v.node.data.id(),
+                                        NodeVariant(&**v),
+                                        DefPathData::EnumVariant(v.node.name));
+
+                    for field in v.node.data.fields() {
+                        self.create_def_with_parent(
+                            Some(variant_def_index),
+                            field.node.id,
+                            DefPathData::Field(field.node.kind));
+                    }
+                }
+            }
+            ItemForeignMod(..) => {
+            }
+            ItemStruct(ref struct_def, _) => {
+                // If this is a tuple-like struct, register the constructor.
+                if !struct_def.is_struct() {
+                    self.insert_def(struct_def.id(),
+                                    NodeStructCtor(struct_def),
+                                    DefPathData::StructCtor);
+                }
+
+                for field in struct_def.fields() {
+                    self.create_def(field.node.id, DefPathData::Field(field.node.kind));
+                }
+            }
+            ItemTrait(_, _, ref bounds, _) => {
+                for b in bounds.iter() {
+                    if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
+                        self.insert(t.trait_ref.ref_id, NodeItem(i));
+                    }
+                }
+            }
+            ItemUse(ref view_path) => {
+                match view_path.node {
+                    ViewPathList(_, ref paths) => {
+                        for path in paths {
+                            self.insert(path.node.id(), NodeItem(i));
+                        }
+                    }
+                    _ => ()
+                }
+            }
+            _ => {}
+        }
+        visit::walk_item(self, i);
+        self.parent_node = parent_node;
+    }
+
+    fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
+        self.insert_def(foreign_item.id,
+                        NodeForeignItem(foreign_item),
+                        DefPathData::Value(foreign_item.name));
+
+        let parent_node = self.parent_node;
+        self.parent_node = foreign_item.id;
+        visit::walk_foreign_item(self, foreign_item);
+        self.parent_node = parent_node;
+    }
+
+    fn visit_generics(&mut self, generics: &'ast Generics) {
+        for ty_param in generics.ty_params.iter() {
+            self.insert_def(ty_param.id,
+                            NodeTyParam(ty_param),
+                            DefPathData::TypeParam(ty_param.name));
+        }
+
+        visit::walk_generics(self, generics);
+    }
+
+    fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
+        let def_data = match ti.node {
+            MethodTraitItem(..) | ConstTraitItem(..) => DefPathData::Value(ti.name),
+            TypeTraitItem(..) => DefPathData::Type(ti.name),
+        };
+
+        self.insert(ti.id, NodeTraitItem(ti));
+        self.create_def(ti.id, def_data);
+
+        let parent_node = self.parent_node;
+        self.parent_node = ti.id;
+
+        match ti.node {
+            ConstTraitItem(_, Some(ref expr)) => {
+                self.create_def(expr.id, DefPathData::Initializer);
+            }
+            _ => { }
+        }
+
+        visit::walk_trait_item(self, ti);
+
+        self.parent_node = parent_node;
+    }
+
+    fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
+        let def_data = match ii.node {
+            MethodImplItem(..) | ConstImplItem(..) => DefPathData::Value(ii.name),
+            TypeImplItem(..) => DefPathData::Type(ii.name),
+        };
+
+        self.insert_def(ii.id, NodeImplItem(ii), def_data);
+
+        let parent_node = self.parent_node;
+        self.parent_node = ii.id;
+
+        match ii.node {
+            ConstImplItem(_, ref expr) => {
+                self.create_def(expr.id, DefPathData::Initializer);
+            }
+            _ => { }
+        }
+
+        visit::walk_impl_item(self, ii);
+
+        self.parent_node = parent_node;
+    }
+
+    fn visit_pat(&mut self, pat: &'ast Pat) {
+        let maybe_binding = match pat.node {
+            PatIdent(_, id, _) => Some(id.node),
+            _ => None
+        };
+
+        if let Some(id) = maybe_binding {
+            self.insert_def(pat.id, NodeLocal(pat), DefPathData::Binding(id.name));
+        } else {
+            self.insert(pat.id, NodePat(pat));
+        }
+
+        let parent_node = self.parent_node;
+        self.parent_node = pat.id;
+        visit::walk_pat(self, pat);
+        self.parent_node = parent_node;
+    }
+
+    fn visit_expr(&mut self, expr: &'ast Expr) {
+        self.insert(expr.id, NodeExpr(expr));
+
+        match expr.node {
+            ExprClosure(..) => { self.create_def(expr.id, DefPathData::ClosureExpr); }
+            _ => { }
+        }
+
+        let parent_node = self.parent_node;
+        self.parent_node = expr.id;
+        visit::walk_expr(self, expr);
+        self.parent_node = parent_node;
+    }
+
+    fn visit_stmt(&mut self, stmt: &'ast Stmt) {
+        let id = util::stmt_id(stmt);
+        self.insert(id, NodeStmt(stmt));
+        let parent_node = self.parent_node;
+        self.parent_node = id;
+        visit::walk_stmt(self, stmt);
+        self.parent_node = parent_node;
+    }
+
+    fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl,
+                b: &'ast Block, s: Span, id: NodeId) {
+        assert_eq!(self.parent_node, id);
+        visit::walk_fn(self, fk, fd, b, s);
+    }
+
+    fn visit_block(&mut self, block: &'ast Block) {
+        self.insert(block.id, NodeBlock(block));
+        let parent_node = self.parent_node;
+        self.parent_node = block.id;
+        visit::walk_block(self, block);
+        self.parent_node = parent_node;
+    }
+
+    fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) {
+        self.insert(lifetime.id, NodeLifetime(lifetime));
+    }
+
+    fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
+        self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
+        self.visit_lifetime(&def.lifetime);
+    }
+
+    fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
+        self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
+    }
+}
+
diff --git a/src/librustc/front/map/definitions.rs b/src/librustc/front/map/definitions.rs
new file mode 100644 (file)
index 0000000..c1eb5f1
--- /dev/null
@@ -0,0 +1,263 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use metadata::cstore::LOCAL_CRATE;
+use middle::def_id::{DefId, DefIndex};
+use rustc_data_structures::fnv::FnvHashMap;
+use rustc_front::hir;
+use syntax::ast;
+use syntax::parse::token::InternedString;
+use util::nodemap::NodeMap;
+
+#[derive(Clone)]
+pub struct Definitions {
+    data: Vec<DefData>,
+    key_map: FnvHashMap<DefKey, DefIndex>,
+    node_map: NodeMap<DefIndex>,
+}
+
+/// A unique identifier that we can use to lookup a definition
+/// precisely. It combines the index of the definition's parent (if
+/// any) with a `DisambiguatedDefPathData`.
+#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+pub struct DefKey {
+    /// Parent path.
+    pub parent: Option<DefIndex>,
+
+    /// Identifier of this node.
+    pub disambiguated_data: DisambiguatedDefPathData,
+}
+
+/// Pair of `DefPathData` and an integer disambiguator. The integer is
+/// normally 0, but in the event that there are multiple defs with the
+/// same `parent` and `data`, we use this field to disambiguate
+/// between them. This introduces some artificial ordering dependency
+/// but means that if you have (e.g.) two impls for the same type in
+/// the same module, they do get distinct def-ids.
+#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+pub struct DisambiguatedDefPathData {
+    pub data: DefPathData,
+    pub disambiguator: u32
+}
+
+/// For each definition, we track the following data.  A definition
+/// here is defined somewhat circularly as "something with a def-id",
+/// but it generally corresponds to things like structs, enums, etc.
+/// There are also some rather random cases (like const initializer
+/// expressions) that are mostly just leftovers.
+#[derive(Clone, Debug)]
+pub struct DefData {
+    pub key: DefKey,
+
+    /// Local ID within the HIR.
+    pub node_id: ast::NodeId,
+}
+
+pub type DefPath = Vec<DisambiguatedDefPathData>;
+
+#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+pub enum DefPathData {
+    // Root: these should only be used for the root nodes, because
+    // they are treated specially by the `def_path` function.
+    CrateRoot,
+    InlinedRoot(DefPath),
+
+    // Catch-all for random DefId things like DUMMY_NODE_ID
+    Misc,
+
+    // Different kinds of items and item-like things:
+    Impl,
+    Type(ast::Name),
+    Mod(ast::Name),
+    Value(ast::Name),
+    MacroDef(ast::Name),
+    ClosureExpr,
+
+    // Subportions of items
+    TypeParam(ast::Name),
+    LifetimeDef(ast::Name),
+    EnumVariant(ast::Name),
+    PositionalField,
+    Field(hir::StructFieldKind),
+    StructCtor, // implicit ctor for a tuple-like struct
+    Initializer, // initializer for a const
+    Binding(ast::Name), // pattern binding
+
+    // An external crate that does not have an `extern crate` in this
+    // crate.
+    DetachedCrate(ast::Name),
+}
+
+impl Definitions {
+    pub fn new() -> Definitions {
+        Definitions {
+            data: vec![],
+            key_map: FnvHashMap(),
+            node_map: NodeMap(),
+        }
+    }
+
+    pub fn len(&self) -> usize {
+        self.data.len()
+    }
+
+    pub fn def_key(&self, index: DefIndex) -> DefKey {
+        self.data[index.as_usize()].key.clone()
+    }
+
+    /// Returns the path from the crate root to `index`. The root
+    /// nodes are not included in the path (i.e., this will be an
+    /// empty vector for the crate root). For an inlined item, this
+    /// will be the path of the item in the external crate (but the
+    /// path will begin with the path to the external crate).
+    pub fn def_path(&self, index: DefIndex) -> DefPath {
+        make_def_path(index, |p| self.def_key(p))
+    }
+
+    pub fn opt_def_index(&self, node: ast::NodeId) -> Option<DefIndex> {
+        self.node_map.get(&node).cloned()
+    }
+
+    pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option<DefId> {
+        self.opt_def_index(node).map(DefId::local)
+    }
+
+    pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
+        if def_id.krate == LOCAL_CRATE {
+            assert!(def_id.index.as_usize() < self.data.len());
+            Some(self.data[def_id.index.as_usize()].node_id)
+        } else {
+            None
+        }
+    }
+
+    pub fn create_def_with_parent(&mut self,
+                                  parent: Option<DefIndex>,
+                                  node_id: ast::NodeId,
+                                  data: DefPathData)
+                                  -> DefIndex {
+        assert!(!self.node_map.contains_key(&node_id),
+                "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
+                node_id,
+                data,
+                self.data[self.node_map[&node_id].as_usize()]);
+
+        // Find a unique DefKey. This basically means incrementing the disambiguator
+        // until we get no match.
+        let mut key = DefKey {
+            parent: parent,
+            disambiguated_data: DisambiguatedDefPathData {
+                data: data,
+                disambiguator: 0
+            }
+        };
+
+        while self.key_map.contains_key(&key) {
+            key.disambiguated_data.disambiguator += 1;
+        }
+
+        // Create the definition.
+        let index = DefIndex::new(self.data.len());
+        self.data.push(DefData { key: key.clone(), node_id: node_id });
+        self.node_map.insert(node_id, index);
+        self.key_map.insert(key, index);
+
+        index
+    }
+}
+
+impl DefPathData {
+    pub fn as_interned_str(&self) -> InternedString {
+        use self::DefPathData::*;
+        match *self {
+            Type(name) |
+            Mod(name) |
+            Value(name) |
+            MacroDef(name) |
+            TypeParam(name) |
+            LifetimeDef(name) |
+            EnumVariant(name) |
+            DetachedCrate(name) |
+            Binding(name) => {
+                name.as_str()
+            }
+
+            Field(hir::StructFieldKind::NamedField(name, _)) => {
+                name.as_str()
+            }
+
+            PositionalField |
+            Field(hir::StructFieldKind::UnnamedField(_)) => {
+                InternedString::new("<field>")
+            }
+
+            // note that this does not show up in user printouts
+            CrateRoot => {
+                InternedString::new("<root>")
+            }
+
+            // note that this does not show up in user printouts
+            InlinedRoot(_) => {
+                InternedString::new("<inlined-root>")
+            }
+
+            Misc => {
+                InternedString::new("?")
+            }
+
+            Impl => {
+                InternedString::new("<impl>")
+            }
+
+            ClosureExpr => {
+                InternedString::new("<closure>")
+            }
+
+            StructCtor => {
+                InternedString::new("<constructor>")
+            }
+
+            Initializer => {
+                InternedString::new("<initializer>")
+            }
+        }
+    }
+
+    pub fn to_string(&self) -> String {
+        self.as_interned_str().to_string()
+    }
+}
+
+pub fn make_def_path<FN>(start_index: DefIndex, mut get_key: FN) -> DefPath
+    where FN: FnMut(DefIndex) -> DefKey
+{
+    let mut result = vec![];
+    let mut index = Some(start_index);
+    while let Some(p) = index {
+        let key = get_key(p);
+        match key.disambiguated_data.data {
+            DefPathData::CrateRoot => {
+                assert!(key.parent.is_none());
+                break;
+            }
+            DefPathData::InlinedRoot(ref p) => {
+                assert!(key.parent.is_none());
+                result.extend(p.iter().cloned().rev());
+                break;
+            }
+            _ => {
+                result.push(key.disambiguated_data);
+                index = key.parent;
+            }
+        }
+    }
+    result.reverse();
+    result
+}
index 764f54ce0f0c1599be263eeae8fa54d33411b116..94800db184e988b97a0db42e1355c2978e34eb8b 100644 (file)
 pub use self::Node::*;
 pub use self::PathElem::*;
 use self::MapEntry::*;
+use self::collector::NodeCollector;
+pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, DisambiguatedDefPathData};
 
 use metadata::inline::InlinedItem;
 use metadata::inline::InlinedItem as II;
 use middle::def_id::DefId;
 
 use syntax::abi;
-use syntax::ast::{Name, NodeId, Ident, CRATE_NODE_ID, DUMMY_NODE_ID};
+use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID};
 use syntax::codemap::{Span, Spanned};
 use syntax::parse::token;
 
 use rustc_front::hir::*;
 use rustc_front::fold::Folder;
-use rustc_front::visit::{self, Visitor};
-use rustc_front::util;
+use rustc_front::visit;
 use rustc_front::print::pprust;
 
 use arena::TypedArena;
 use std::cell::RefCell;
 use std::fmt;
 use std::io;
-use std::iter::{self, repeat};
+use std::iter;
 use std::mem;
 use std::slice;
 
 pub mod blocks;
+mod collector;
+pub mod definitions;
 
 #[derive(Clone, Copy, PartialEq, Debug)]
 pub enum PathElem {
@@ -115,13 +118,12 @@ pub enum Node<'ast> {
     NodeVariant(&'ast Variant),
     NodeExpr(&'ast Expr),
     NodeStmt(&'ast Stmt),
-    NodeArg(&'ast Pat),
     NodeLocal(&'ast Pat),
     NodePat(&'ast Pat),
     NodeBlock(&'ast Block),
 
     /// NodeStructCtor represents a tuple struct.
-    NodeStructCtor(&'ast StructDef),
+    NodeStructCtor(&'ast VariantData),
 
     NodeLifetime(&'ast Lifetime),
     NodeTyParam(&'ast TyParam)
@@ -130,7 +132,7 @@ pub enum Node<'ast> {
 /// Represents an entry and its parent NodeID.
 /// The odd layout is to bring down the total size.
 #[derive(Copy, Debug)]
-enum MapEntry<'ast> {
+pub enum MapEntry<'ast> {
     /// Placeholder for holes in the map.
     NotPresent,
 
@@ -142,11 +144,10 @@ enum MapEntry<'ast> {
     EntryVariant(NodeId, &'ast Variant),
     EntryExpr(NodeId, &'ast Expr),
     EntryStmt(NodeId, &'ast Stmt),
-    EntryArg(NodeId, &'ast Pat),
     EntryLocal(NodeId, &'ast Pat),
     EntryPat(NodeId, &'ast Pat),
     EntryBlock(NodeId, &'ast Block),
-    EntryStructCtor(NodeId, &'ast StructDef),
+    EntryStructCtor(NodeId, &'ast VariantData),
     EntryLifetime(NodeId, &'ast Lifetime),
     EntryTyParam(NodeId, &'ast TyParam),
 
@@ -177,7 +178,6 @@ impl<'ast> MapEntry<'ast> {
             NodeVariant(n) => EntryVariant(p, n),
             NodeExpr(n) => EntryExpr(p, n),
             NodeStmt(n) => EntryStmt(p, n),
-            NodeArg(n) => EntryArg(p, n),
             NodeLocal(n) => EntryLocal(p, n),
             NodePat(n) => EntryPat(p, n),
             NodeBlock(n) => EntryBlock(p, n),
@@ -196,7 +196,6 @@ impl<'ast> MapEntry<'ast> {
             EntryVariant(id, _) => id,
             EntryExpr(id, _) => id,
             EntryStmt(id, _) => id,
-            EntryArg(id, _) => id,
             EntryLocal(id, _) => id,
             EntryPat(id, _) => id,
             EntryBlock(id, _) => id,
@@ -216,7 +215,6 @@ impl<'ast> MapEntry<'ast> {
             EntryVariant(_, n) => NodeVariant(n),
             EntryExpr(_, n) => NodeExpr(n),
             EntryStmt(_, n) => NodeStmt(n),
-            EntryArg(_, n) => NodeArg(n),
             EntryLocal(_, n) => NodeLocal(n),
             EntryPat(_, n) => NodePat(n),
             EntryBlock(_, n) => NodeBlock(n),
@@ -263,10 +261,45 @@ pub struct Map<'ast> {
     ///
     /// Also, indexing is pretty quick when you've got a vector and
     /// plain old integers.
-    map: RefCell<Vec<MapEntry<'ast>>>
+    map: RefCell<Vec<MapEntry<'ast>>>,
+
+    definitions: RefCell<Definitions>,
 }
 
 impl<'ast> Map<'ast> {
+    pub fn num_local_def_ids(&self) -> usize {
+        self.definitions.borrow().len()
+    }
+
+    pub fn def_key(&self, def_id: DefId) -> DefKey {
+        assert!(def_id.is_local());
+        self.definitions.borrow().def_key(def_id.index)
+    }
+
+    pub fn def_path_from_id(&self, id: NodeId) -> DefPath {
+        self.def_path(self.local_def_id(id))
+    }
+
+    pub fn def_path(&self, def_id: DefId) -> DefPath {
+        assert!(def_id.is_local());
+        self.definitions.borrow().def_path(def_id.index)
+    }
+
+    pub fn local_def_id(&self, node: NodeId) -> DefId {
+        self.opt_local_def_id(node).unwrap_or_else(|| {
+            panic!("local_def_id: no entry for `{}`, which has a map of `{:?}`",
+                   node, self.find_entry(node))
+        })
+    }
+
+    pub fn opt_local_def_id(&self, node: NodeId) -> Option<DefId> {
+        self.definitions.borrow().opt_local_def_id(node)
+    }
+
+    pub fn as_local_node_id(&self, def_id: DefId) -> Option<NodeId> {
+        self.definitions.borrow().as_local_node_id(def_id)
+    }
+
     fn entry_count(&self) -> usize {
         self.map.borrow().len()
     }
@@ -288,6 +321,10 @@ impl<'ast> Map<'ast> {
         }
     }
 
+    pub fn get_if_local(&self, id: DefId) -> Option<Node<'ast>> {
+        self.as_local_node_id(id).map(|id| self.get(id))
+    }
+
     /// Retrieve the Node corresponding to `id`, returning None if
     /// cannot be found.
     pub fn find(&self, id: NodeId) -> Option<Node<'ast>> {
@@ -306,6 +343,27 @@ impl<'ast> Map<'ast> {
         self.find_entry(id).and_then(|x| x.parent_node()).unwrap_or(id)
     }
 
+    /// Check if the node is an argument. An argument is a local variable whose
+    /// immediate parent is an item or a closure.
+    pub fn is_argument(&self, id: NodeId) -> bool {
+        match self.find(id) {
+            Some(NodeLocal(_)) => (),
+            _ => return false,
+        }
+        match self.find(self.get_parent_node(id)) {
+            Some(NodeItem(_)) |
+            Some(NodeTraitItem(_)) |
+            Some(NodeImplItem(_)) => true,
+            Some(NodeExpr(e)) => {
+                match e.node {
+                    ExprClosure(..) => true,
+                    _ => false,
+                }
+            }
+            _ => false,
+        }
+    }
+
     /// If there is some error when walking the parents (e.g., a node does not
     /// have a parent in the map or a node can't be found), then we return the
     /// last good node id we found. Note that reaching the crate root (id == 0),
@@ -383,7 +441,7 @@ impl<'ast> Map<'ast> {
         match self.find_entry(parent) {
             Some(RootInlinedParent(&InlinedParent {ii: II::TraitItem(did, _), ..})) => did,
             Some(RootInlinedParent(&InlinedParent {ii: II::ImplItem(did, _), ..})) => did,
-            _ => DefId::local(parent)
+            _ => self.local_def_id(parent)
         }
     }
 
@@ -429,18 +487,19 @@ impl<'ast> Map<'ast> {
         }
     }
 
-    pub fn expect_struct(&self, id: NodeId) -> &'ast StructDef {
+    pub fn expect_struct(&self, id: NodeId) -> &'ast VariantData {
         match self.find(id) {
             Some(NodeItem(i)) => {
                 match i.node {
-                    ItemStruct(ref struct_def, _) => &**struct_def,
+                    ItemStruct(ref struct_def, _) => struct_def,
                     _ => panic!("struct ID bound to non-struct")
                 }
             }
             Some(NodeVariant(variant)) => {
-                match variant.node.kind {
-                    StructVariantKind(ref struct_def) => &**struct_def,
-                    _ => panic!("struct ID bound to enum variant that isn't struct-like"),
+                if variant.node.data.is_struct() {
+                    &variant.node.data
+                } else {
+                    panic!("struct ID bound to enum variant that isn't struct-like")
                 }
             }
             _ => panic!(format!("expected struct, found {}", self.node_to_string(id))),
@@ -475,16 +534,20 @@ impl<'ast> Map<'ast> {
             NodeItem(item) => {
                 match item.node {
                     ItemMod(_) | ItemForeignMod(_) => {
-                        PathMod(item.ident.name)
+                        PathMod(item.name)
                     }
-                    _ => PathName(item.ident.name)
+                    _ => PathName(item.name)
                 }
             }
-            NodeForeignItem(i) => PathName(i.ident.name),
-            NodeImplItem(ii) => PathName(ii.ident.name),
-            NodeTraitItem(ti) => PathName(ti.ident.name),
-            NodeVariant(v) => PathName(v.node.name.name),
+            NodeForeignItem(i) => PathName(i.name),
+            NodeImplItem(ii) => PathName(ii.name),
+            NodeTraitItem(ti) => PathName(ti.name),
+            NodeVariant(v) => PathName(v.node.name),
             NodeLifetime(lt) => PathName(lt.name),
+            NodeTyParam(tp) => PathName(tp.name),
+            NodeLocal(&Pat { node: PatIdent(_,l,_), .. }) => {
+                PathName(l.node.name)
+            },
             _ => panic!("no path elem for {:?}", node)
         }
     }
@@ -499,9 +562,9 @@ impl<'ast> Map<'ast> {
         self.with_path(id, |path| path_to_string(path))
     }
 
-    fn path_to_str_with_ident(&self, id: NodeId, i: Ident) -> String {
+    fn path_to_str_with_name(&self, id: NodeId, name: Name) -> String {
         self.with_path(id, |path| {
-            path_to_string(path.chain(Some(PathName(i.name))))
+            path_to_string(path.chain(Some(PathName(name))))
         })
     }
 
@@ -536,9 +599,9 @@ impl<'ast> Map<'ast> {
         }
     }
 
-    /// Given a node ID, get a list of of attributes associated with the AST
+    /// Given a node ID, get a list of attributes associated with the AST
     /// corresponding to the Node ID
-    pub fn attrs(&self, id: NodeId) -> &'ast [Attribute] {
+    pub fn attrs(&self, id: NodeId) -> &'ast [ast::Attribute] {
         let attrs = match self.find(id) {
             Some(NodeItem(i)) => Some(&i.attrs[..]),
             Some(NodeForeignItem(fi)) => Some(&fi.attrs[..]),
@@ -581,7 +644,7 @@ impl<'ast> Map<'ast> {
             Some(NodeVariant(variant)) => variant.span,
             Some(NodeExpr(expr)) => expr.span,
             Some(NodeStmt(stmt)) => stmt.span,
-            Some(NodeArg(pat)) | Some(NodeLocal(pat)) => pat.span,
+            Some(NodeLocal(pat)) => pat.span,
             Some(NodePat(pat)) => pat.span,
             Some(NodeBlock(block)) => block.span,
             Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span,
@@ -596,9 +659,13 @@ impl<'ast> Map<'ast> {
             .unwrap_or_else(|| panic!("AstMap.span: could not find span for id {:?}", id))
     }
 
+    pub fn span_if_local(&self, id: DefId) -> Option<Span> {
+        self.as_local_node_id(id).map(|id| self.span(id))
+    }
+
     pub fn def_id_span(&self, def_id: DefId, fallback: Span) -> Span {
-        if def_id.is_local() {
-            self.opt_span(def_id.node).unwrap_or(fallback)
+        if let Some(node_id) = self.as_local_node_id(def_id) {
+            self.opt_span(node_id).unwrap_or(fallback)
         } else {
             fallback
         }
@@ -652,7 +719,7 @@ impl<'a, 'ast> NodesMatchingSuffix<'a, 'ast> {
                 match map.find(id) {
                     None => return None,
                     Some(NodeItem(item)) if item_is_mod(&*item) =>
-                        return Some((id, item.ident.name)),
+                        return Some((id, item.name)),
                     _ => {}
                 }
                 let parent = map.get_parent(id);
@@ -708,11 +775,11 @@ trait Named {
 
 impl<T:Named> Named for Spanned<T> { fn name(&self) -> Name { self.node.name() } }
 
-impl Named for Item { fn name(&self) -> Name { self.ident.name } }
-impl Named for ForeignItem { fn name(&self) -> Name { self.ident.name } }
-impl Named for Variant_ { fn name(&self) -> Name { self.name.name } }
-impl Named for TraitItem { fn name(&self) -> Name { self.ident.name } }
-impl Named for ImplItem { fn name(&self) -> Name { self.ident.name } }
+impl Named for Item { fn name(&self) -> Name { self.name } }
+impl Named for ForeignItem { fn name(&self) -> Name { self.name } }
+impl Named for Variant_ { fn name(&self) -> Name { self.name } }
+impl Named for TraitItem { fn name(&self) -> Name { self.name } }
+impl Named for ImplItem { fn name(&self) -> Name { self.name } }
 
 pub trait FoldOps {
     fn new_id(&self, id: NodeId) -> NodeId {
@@ -741,194 +808,10 @@ impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
     }
 }
 
-/// A Visitor that walks over an AST and collects Node's into an AST Map.
-struct NodeCollector<'ast> {
-    map: Vec<MapEntry<'ast>>,
-    parent_node: NodeId,
-}
-
-impl<'ast> NodeCollector<'ast> {
-    fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'ast>) {
-        debug!("ast_map: {:?} => {:?}", id, entry);
-        let len = self.map.len();
-        if id as usize >= len {
-            self.map.extend(repeat(NotPresent).take(id as usize - len + 1));
-        }
-        self.map[id as usize] = entry;
-    }
-
-    fn insert(&mut self, id: NodeId, node: Node<'ast>) {
-        let entry = MapEntry::from_node(self.parent_node, node);
-        self.insert_entry(id, entry);
-    }
-
-    fn visit_fn_decl(&mut self, decl: &'ast FnDecl) {
-        for a in &decl.inputs {
-            self.insert(a.id, NodeArg(&*a.pat));
-        }
-    }
-}
-
-impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
-    fn visit_item(&mut self, i: &'ast Item) {
-        self.insert(i.id, NodeItem(i));
-
-        let parent_node = self.parent_node;
-        self.parent_node = i.id;
-
-        match i.node {
-            ItemImpl(_, _, _, _, _, ref impl_items) => {
-                for ii in impl_items {
-                    self.insert(ii.id, NodeImplItem(ii));
-                }
-            }
-            ItemEnum(ref enum_definition, _) => {
-                for v in &enum_definition.variants {
-                    self.insert(v.node.id, NodeVariant(&**v));
-                }
-            }
-            ItemForeignMod(ref nm) => {
-                for nitem in &nm.items {
-                    self.insert(nitem.id, NodeForeignItem(&**nitem));
-                }
-            }
-            ItemStruct(ref struct_def, _) => {
-                // If this is a tuple-like struct, register the constructor.
-                match struct_def.ctor_id {
-                    Some(ctor_id) => {
-                        self.insert(ctor_id, NodeStructCtor(&**struct_def));
-                    }
-                    None => {}
-                }
-            }
-            ItemTrait(_, _, ref bounds, ref trait_items) => {
-                for b in bounds.iter() {
-                    if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
-                        self.insert(t.trait_ref.ref_id, NodeItem(i));
-                    }
-                }
-
-                for ti in trait_items {
-                    self.insert(ti.id, NodeTraitItem(ti));
-                }
-            }
-            ItemUse(ref view_path) => {
-                match view_path.node {
-                    ViewPathList(_, ref paths) => {
-                        for path in paths {
-                            self.insert(path.node.id(), NodeItem(i));
-                        }
-                    }
-                    _ => ()
-                }
-            }
-            _ => {}
-        }
-        visit::walk_item(self, i);
-        self.parent_node = parent_node;
-    }
-
-    fn visit_generics(&mut self, generics: &'ast Generics) {
-        for ty_param in generics.ty_params.iter() {
-            self.insert(ty_param.id, NodeTyParam(ty_param));
-        }
-
-        visit::walk_generics(self, generics);
-    }
-
-    fn visit_trait_item(&mut self, ti: &'ast TraitItem) {
-        let parent_node = self.parent_node;
-        self.parent_node = ti.id;
-        visit::walk_trait_item(self, ti);
-        self.parent_node = parent_node;
-    }
-
-    fn visit_impl_item(&mut self, ii: &'ast ImplItem) {
-        let parent_node = self.parent_node;
-        self.parent_node = ii.id;
-
-        visit::walk_impl_item(self, ii);
-
-        self.parent_node = parent_node;
-    }
-
-    fn visit_pat(&mut self, pat: &'ast Pat) {
-        self.insert(pat.id, match pat.node {
-            // Note: this is at least *potentially* a pattern...
-            PatIdent(..) => NodeLocal(pat),
-            _ => NodePat(pat)
-        });
-
-        let parent_node = self.parent_node;
-        self.parent_node = pat.id;
-        visit::walk_pat(self, pat);
-        self.parent_node = parent_node;
-    }
-
-    fn visit_expr(&mut self, expr: &'ast Expr) {
-        self.insert(expr.id, NodeExpr(expr));
-        let parent_node = self.parent_node;
-        self.parent_node = expr.id;
-        visit::walk_expr(self, expr);
-        self.parent_node = parent_node;
-    }
-
-    fn visit_stmt(&mut self, stmt: &'ast Stmt) {
-        let id = util::stmt_id(stmt);
-        self.insert(id, NodeStmt(stmt));
-        let parent_node = self.parent_node;
-        self.parent_node = id;
-        visit::walk_stmt(self, stmt);
-        self.parent_node = parent_node;
-    }
-
-    fn visit_fn(&mut self, fk: visit::FnKind<'ast>, fd: &'ast FnDecl,
-                b: &'ast Block, s: Span, id: NodeId) {
-        let parent_node = self.parent_node;
-        self.parent_node = id;
-        self.visit_fn_decl(fd);
-        visit::walk_fn(self, fk, fd, b, s);
-        self.parent_node = parent_node;
-    }
-
-    fn visit_ty(&mut self, ty: &'ast Ty) {
-        let parent_node = self.parent_node;
-        self.parent_node = ty.id;
-        match ty.node {
-            TyBareFn(ref fd) => {
-                self.visit_fn_decl(&*fd.decl);
-            }
-            _ => {}
-        }
-        visit::walk_ty(self, ty);
-        self.parent_node = parent_node;
-    }
-
-    fn visit_block(&mut self, block: &'ast Block) {
-        self.insert(block.id, NodeBlock(block));
-        let parent_node = self.parent_node;
-        self.parent_node = block.id;
-        visit::walk_block(self, block);
-        self.parent_node = parent_node;
-    }
-
-    fn visit_lifetime_ref(&mut self, lifetime: &'ast Lifetime) {
-        self.insert(lifetime.id, NodeLifetime(lifetime));
-    }
-
-    fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
-        self.visit_lifetime_ref(&def.lifetime);
-    }
-}
-
 pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
-    let mut collector = NodeCollector {
-        map: vec![],
-        parent_node: CRATE_NODE_ID,
-    };
-    collector.insert_entry(CRATE_NODE_ID, RootCrate);
+    let mut collector = NodeCollector::root();
     visit::walk_crate(&mut collector, &forest.krate);
-    let map = collector.map;
+    let NodeCollector { map, definitions, .. } = collector;
 
     if log_enabled!(::log::DEBUG) {
         // This only makes sense for ordered stores; note the
@@ -948,7 +831,8 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
 
     Map {
         forest: forest,
-        map: RefCell::new(map)
+        map: RefCell::new(map),
+        definitions: RefCell::new(definitions),
     }
 }
 
@@ -957,6 +841,7 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest) -> Map<'ast> {
 /// the item itself.
 pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
                                           path: Vec<PathElem>,
+                                          def_path: DefPath,
                                           ii: InlinedItem,
                                           fold_ops: F)
                                           -> &'ast InlinedItem {
@@ -980,29 +865,18 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
     });
 
     let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
-    let mut collector = NodeCollector {
-        map: mem::replace(&mut *map.map.borrow_mut(), vec![]),
-        parent_node: ii_parent_id,
-    };
-    collector.insert_entry(ii_parent_id, RootInlinedParent(ii_parent));
+    let mut collector =
+        NodeCollector::extend(
+            ii_parent,
+            ii_parent_id,
+            def_path,
+            mem::replace(&mut *map.map.borrow_mut(), vec![]),
+            mem::replace(&mut *map.definitions.borrow_mut(), Definitions::new()));
     ii_parent.ii.visit(&mut collector);
 
-    // Methods get added to the AST map when their impl is visited.  Since we
-    // don't decode and instantiate the impl, but just the method, we have to
-    // add it to the table now. Likewise with foreign items.
-    match ii_parent.ii {
-        II::Item(_) => {}
-        II::TraitItem(_, ref ti) => {
-            collector.insert(ti.id, NodeTraitItem(ti));
-        }
-        II::ImplItem(_, ref ii) => {
-            collector.insert(ii.id, NodeImplItem(ii));
-        }
-        II::Foreign(ref i) => {
-            collector.insert(i.id, NodeForeignItem(i));
-        }
-    }
     *map.map.borrow_mut() = collector.map;
+    *map.definitions.borrow_mut() = collector.definitions;
+
     &ii_parent.ii
 }
 
@@ -1028,7 +902,6 @@ impl<'a> NodePrinter for pprust::State<'a> {
             // ast_map to reconstruct their full structure for pretty
             // printing.
             NodeLocal(_)       => panic!("cannot print isolated Local"),
-            NodeArg(_)         => panic!("cannot print isolated Arg"),
             NodeStructCtor(_)  => panic!("cannot print isolated StructCtor"),
         }
     }
@@ -1040,7 +913,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
 
     match map.find(id) {
         Some(NodeItem(item)) => {
-            let path_str = map.path_to_str_with_ident(id, item.ident);
+            let path_str = map.path_to_str_with_name(id, item.name);
             let item_str = match item.node {
                 ItemExternCrate(..) => "extern crate",
                 ItemUse(..) => "use",
@@ -1059,25 +932,25 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
             format!("{} {}{}", item_str, path_str, id_str)
         }
         Some(NodeForeignItem(item)) => {
-            let path_str = map.path_to_str_with_ident(id, item.ident);
+            let path_str = map.path_to_str_with_name(id, item.name);
             format!("foreign item {}{}", path_str, id_str)
         }
         Some(NodeImplItem(ii)) => {
             match ii.node {
                 ConstImplItem(..) => {
                     format!("assoc const {} in {}{}",
-                            ii.ident,
+                            ii.name,
                             map.path_to_string(id),
                             id_str)
                 }
                 MethodImplItem(..) => {
                     format!("method {} in {}{}",
-                            ii.ident,
+                            ii.name,
                             map.path_to_string(id), id_str)
                 }
                 TypeImplItem(_) => {
                     format!("assoc type {} in {}{}",
-                            ii.ident,
+                            ii.name,
                             map.path_to_string(id),
                             id_str)
                 }
@@ -1092,7 +965,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
 
             format!("{} {} in {}{}",
                     kind,
-                    ti.ident,
+                    ti.name,
                     map.path_to_string(id),
                     id_str)
         }
@@ -1107,9 +980,6 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
         Some(NodeStmt(ref stmt)) => {
             format!("stmt {}{}", pprust::stmt_to_string(&**stmt), id_str)
         }
-        Some(NodeArg(ref pat)) => {
-            format!("arg {}{}", pprust::pat_to_string(&**pat), id_str)
-        }
         Some(NodeLocal(ref pat)) => {
             format!("local {}{}", pprust::pat_to_string(&**pat), id_str)
         }
index cfeab976e24cb110d00a1dff96289c8b4f4a82e3..393329b42147c770975746d5667d0dc221495fc0 100644 (file)
@@ -35,7 +35,6 @@
 #![feature(duration_span)]
 #![feature(dynamic_lib)]
 #![feature(enumset)]
-#![feature(fs_canonicalize)]
 #![feature(hashmap_hasher)]
 #![feature(into_cow)]
 #![feature(iter_cmp)]
 #![feature(libc)]
 #![feature(nonzero)]
 #![feature(num_bits_bytes)]
-#![feature(path_ext)]
 #![feature(quote)]
-#![feature(range_inclusive)]
-#![feature(ref_slice)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 #![feature(scoped_tls)]
-#![feature(slice_splits)]
 #![feature(slice_patterns)]
 #![feature(staged_api)]
 #![feature(str_char)]
-#![feature(str_match_indices)]
 #![feature(vec_push_all)]
 #![feature(wrapping)]
 #![feature(cell_extras)]
@@ -101,10 +95,12 @@ pub mod back {
 }
 
 pub mod front {
+    pub mod check_attr;
     pub mod map;
 }
 
 pub mod middle {
+    pub mod expr_use_visitor; // STAGE0: increase glitch immunity
     pub mod astconv_util;
     pub mod astencode;
     pub mod cfg;
@@ -122,7 +118,6 @@ pub mod middle {
     pub mod dependency_format;
     pub mod effect;
     pub mod entry;
-    pub mod expr_use_visitor;
     pub mod free_region;
     pub mod intrinsicck;
     pub mod infer;
index 495044f9459494f738fa501c229b69de93f22da3..26f663b1c9d79de988cc608688f4cec78914e3a6 100644 (file)
 //! compiler code, rather than using their own custom pass. Those
 //! lints are all available in `rustc_lint::builtin`.
 
-use lint::{LintPass, LintArray};
+use lint::{LintPass, LateLintPass, LintArray};
+
+declare_lint! {
+    pub CONST_ERR,
+    Warn,
+    "constant evaluation detected erroneous expression"
+}
 
 declare_lint! {
     pub UNUSED_IMPORTS,
@@ -134,7 +140,10 @@ impl LintPass for HardwiredLints {
             VARIANT_SIZE_DIFFERENCES,
             FAT_PTR_TRANSMUTES,
             TRIVIAL_CASTS,
-            TRIVIAL_NUMERIC_CASTS
+            TRIVIAL_NUMERIC_CASTS,
+            CONST_ERR
         )
     }
 }
+
+impl LateLintPass for HardwiredLints {}
index 67be93cc2bdc6425ea6b62e704702a17b09db8d8..e3eac2e6068076ef20177cf48dd282b593ef321b 100644 (file)
@@ -28,7 +28,8 @@ use self::TargetLint::*;
 use middle::privacy::ExportedItems;
 use middle::ty::{self, Ty};
 use session::{early_error, Session};
-use lint::{Level, LevelSource, Lint, LintId, LintArray, LintPass, LintPassObject};
+use lint::{Level, LevelSource, Lint, LintId, LintArray, LintPass};
+use lint::{EarlyLintPass, EarlyLintPassObject, LateLintPass, LateLintPassObject};
 use lint::{Default, CommandLine, Node, Allow, Warn, Deny, Forbid};
 use lint::builtin;
 use util::nodemap::FnvHashMap;
@@ -36,15 +37,15 @@ use util::nodemap::FnvHashMap;
 use std::cell::RefCell;
 use std::cmp;
 use std::mem;
-use syntax::ast_util::IdVisitingOperation;
-use rustc_front::attr::{self, AttrMetaMethods};
-use rustc_front::util;
+use syntax::ast_util::{self, IdVisitingOperation};
+use syntax::attr::{self, AttrMetaMethods};
 use syntax::codemap::Span;
 use syntax::parse::token::InternedString;
 use syntax::ast;
 use rustc_front::hir;
-use rustc_front::visit::{self, Visitor, FnKind};
-use syntax::visit::Visitor as SyntaxVisitor;
+use rustc_front::util;
+use rustc_front::visit as hir_visit;
+use syntax::visit as ast_visit;
 use syntax::diagnostic;
 
 /// Information about the registered lints.
@@ -59,7 +60,8 @@ pub struct LintStore {
     /// Trait objects for each lint pass.
     /// This is only `None` while iterating over the objects. See the definition
     /// of run_lints.
-    passes: Option<Vec<LintPassObject>>,
+    early_passes: Option<Vec<EarlyLintPassObject>>,
+    late_passes: Option<Vec<LateLintPassObject>>,
 
     /// Lints indexed by name.
     by_name: FnvHashMap<String, TargetLint>,
@@ -115,7 +117,8 @@ impl LintStore {
     pub fn new() -> LintStore {
         LintStore {
             lints: vec!(),
-            passes: Some(vec!()),
+            early_passes: Some(vec!()),
+            late_passes: Some(vec!()),
             by_name: FnvHashMap(),
             levels: FnvHashMap(),
             lint_groups: FnvHashMap(),
@@ -133,8 +136,27 @@ impl LintStore {
                                               v.1)).collect()
     }
 
-    pub fn register_pass(&mut self, sess: Option<&Session>,
-                         from_plugin: bool, pass: LintPassObject) {
+    pub fn register_early_pass(&mut self,
+                               sess: Option<&Session>,
+                               from_plugin: bool,
+                               pass: EarlyLintPassObject) {
+        self.push_pass(sess, from_plugin, &pass);
+        self.early_passes.as_mut().unwrap().push(pass);
+    }
+
+    pub fn register_late_pass(&mut self,
+                              sess: Option<&Session>,
+                              from_plugin: bool,
+                              pass: LateLintPassObject) {
+        self.push_pass(sess, from_plugin, &pass);
+        self.late_passes.as_mut().unwrap().push(pass);
+    }
+
+    // Helper method for register_early/late_pass
+    fn push_pass<P: LintPass + ?Sized + 'static>(&mut self,
+                                        sess: Option<&Session>,
+                                        from_plugin: bool,
+                                        pass: &Box<P>) {
         for &lint in pass.get_lints() {
             self.lints.push((*lint, from_plugin));
 
@@ -156,7 +178,6 @@ impl LintStore {
                 self.levels.insert(id, (lint.default_level, Default));
             }
         }
-        self.passes.as_mut().unwrap().push(pass);
     }
 
     pub fn register_group(&mut self, sess: Option<&Session>,
@@ -248,8 +269,8 @@ impl LintStore {
     }
 }
 
-/// Context for lint checking.
-pub struct Context<'a, 'tcx: 'a> {
+/// Context for lint checking after type checking.
+pub struct LateContext<'a, 'tcx: 'a> {
     /// Type context we're checking in.
     pub tcx: &'a ty::ctxt<'tcx>,
 
@@ -272,21 +293,39 @@ pub struct Context<'a, 'tcx: 'a> {
     node_levels: RefCell<FnvHashMap<(ast::NodeId, LintId), LevelSource>>,
 }
 
+/// Context for lint checking of the AST, after expansion, before lowering to
+/// HIR.
+pub struct EarlyContext<'a> {
+    /// Type context we're checking in.
+    pub sess: &'a Session,
+
+    /// The crate being checked.
+    pub krate: &'a ast::Crate,
+
+    /// The store of registered lints.
+    lints: LintStore,
+
+    /// When recursing into an attributed node of the ast which modifies lint
+    /// levels, this stack keeps track of the previous lint levels of whatever
+    /// was modified.
+    level_stack: Vec<(LintId, LevelSource)>,
+}
+
 /// Convenience macro for calling a `LintPass` method on every pass in the context.
-macro_rules! run_lints { ($cx:expr, $f:ident, $($args:expr),*) => ({
+macro_rules! run_lints { ($cx:expr, $f:ident, $ps:ident, $($args:expr),*) => ({
     // Move the vector of passes out of `$cx` so that we can
     // iterate over it mutably while passing `$cx` to the methods.
-    let mut passes = $cx.lints.passes.take().unwrap();
+    let mut passes = $cx.mut_lints().$ps.take().unwrap();
     for obj in &mut passes {
         obj.$f($cx, $($args),*);
     }
-    $cx.lints.passes = Some(passes);
+    $cx.mut_lints().$ps = Some(passes);
 }) }
 
 /// Parse the lint attributes into a vector, with `Err`s for malformed lint
 /// attributes. Writing this as an iterator is an enormous mess.
 // See also the hir version just below.
-pub fn gather_attrs(attrs: &[hir::Attribute])
+pub fn gather_attrs(attrs: &[ast::Attribute])
                     -> Vec<Result<(InternedString, Level, Span), Span>> {
     let mut out = vec!();
     for attr in attrs {
@@ -299,7 +338,7 @@ pub fn gather_attrs(attrs: &[hir::Attribute])
 
         let meta = &attr.node.value;
         let metas = match meta.node {
-            hir::MetaList(_, ref metas) => metas,
+            ast::MetaList(_, ref metas) => metas,
             _ => {
                 out.push(Err(meta.span));
                 continue;
@@ -308,41 +347,7 @@ pub fn gather_attrs(attrs: &[hir::Attribute])
 
         for meta in metas {
             out.push(match meta.node {
-                hir::MetaWord(ref lint_name) => Ok((lint_name.clone(), level, meta.span)),
-                _ => Err(meta.span),
-            });
-        }
-    }
-    out
-}
-// Copy-pasted from the above function :-(
-pub fn gather_attrs_from_hir(attrs: &[::rustc_front::hir::Attribute])
-                             -> Vec<Result<(InternedString, Level, Span), Span>> {
-    use ::rustc_front::attr::AttrMetaMethods;
-
-    let mut out = vec!();
-    for attr in attrs {
-        let level = match Level::from_str(&attr.name()) {
-            None => continue,
-            Some(lvl) => lvl,
-        };
-
-        ::rustc_front::attr::mark_used(attr);
-
-        let meta = &attr.node.value;
-        let metas = match meta.node {
-            ::rustc_front::hir::MetaList(_, ref metas) => metas,
-            _ => {
-                out.push(Err(meta.span));
-                continue;
-            }
-        };
-
-        for meta in metas {
-            out.push(match meta.node {
-                ::rustc_front::hir::MetaWord(ref lint_name) => {
-                    Ok((lint_name.clone(), level, meta.span))
-                }
+                ast::MetaWord(ref lint_name) => Ok((lint_name.clone(), level, meta.span)),
                 _ => Err(meta.span),
             });
         }
@@ -398,65 +403,72 @@ pub fn raw_emit_lint(sess: &Session, lint: &'static Lint,
     }
 }
 
-impl<'a, 'tcx> Context<'a, 'tcx> {
-    fn new(tcx: &'a ty::ctxt<'tcx>,
-           krate: &'a hir::Crate,
-           exported_items: &'a ExportedItems) -> Context<'a, 'tcx> {
-        // We want to own the lint store, so move it out of the session.
-        let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(),
-                                      LintStore::new());
-
-        Context {
-            tcx: tcx,
-            krate: krate,
-            exported_items: exported_items,
-            lints: lint_store,
-            level_stack: vec![],
-            node_levels: RefCell::new(FnvHashMap()),
-        }
-    }
-
-    /// Get the overall compiler `Session` object.
-    pub fn sess(&'a self) -> &'a Session {
-        &self.tcx.sess
-    }
+pub trait LintContext: Sized {
+    fn sess(&self) -> &Session;
+    fn lints(&self) -> &LintStore;
+    fn mut_lints(&mut self) -> &mut LintStore;
+    fn level_stack(&mut self) -> &mut Vec<(LintId, LevelSource)>;
+    fn enter_attrs(&mut self, attrs: &[ast::Attribute]);
+    fn exit_attrs(&mut self, attrs: &[ast::Attribute]);
 
     /// Get the level of `lint` at the current position of the lint
     /// traversal.
-    pub fn current_level(&self, lint: &'static Lint) -> Level {
-        self.lints.levels.get(&LintId::of(lint)).map_or(Allow, |&(lvl, _)| lvl)
+    fn current_level(&self, lint: &'static Lint) -> Level {
+        self.lints().levels.get(&LintId::of(lint)).map_or(Allow, |&(lvl, _)| lvl)
     }
 
     fn lookup_and_emit(&self, lint: &'static Lint, span: Option<Span>, msg: &str) {
-        let (level, src) = match self.lints.levels.get(&LintId::of(lint)) {
+        let (level, src) = match self.lints().levels.get(&LintId::of(lint)) {
             None => return,
             Some(&(Warn, src)) => {
                 let lint_id = LintId::of(builtin::WARNINGS);
-                (self.lints.get_level_source(lint_id).0, src)
+                (self.lints().get_level_source(lint_id).0, src)
             }
             Some(&pair) => pair,
         };
 
-        raw_emit_lint(&self.tcx.sess, lint, (level, src), span, msg);
-    }
-
-    /// Emit a lint at the appropriate level, with no associated span.
-    pub fn lint(&self, lint: &'static Lint, msg: &str) {
-        self.lookup_and_emit(lint, None, msg);
+        raw_emit_lint(&self.sess(), lint, (level, src), span, msg);
     }
 
     /// Emit a lint at the appropriate level, for a particular span.
-    pub fn span_lint(&self, lint: &'static Lint, span: Span, msg: &str) {
+    fn span_lint(&self, lint: &'static Lint, span: Span, msg: &str) {
         self.lookup_and_emit(lint, Some(span), msg);
     }
 
+    /// Emit a lint and note at the appropriate level, for a particular span.
+    fn span_lint_note(&self, lint: &'static Lint, span: Span, msg: &str,
+                      note_span: Span, note: &str) {
+        self.span_lint(lint, span, msg);
+        if self.current_level(lint) != Level::Allow {
+            if note_span == span {
+                self.sess().fileline_note(note_span, note)
+            } else {
+                self.sess().span_note(note_span, note)
+            }
+        }
+    }
+
+    /// Emit a lint and help at the appropriate level, for a particular span.
+    fn span_lint_help(&self, lint: &'static Lint, span: Span,
+                      msg: &str, help: &str) {
+        self.span_lint(lint, span, msg);
+        if self.current_level(lint) != Level::Allow {
+            self.sess().span_help(span, help)
+        }
+    }
+
+    /// Emit a lint at the appropriate level, with no associated span.
+    fn lint(&self, lint: &'static Lint, msg: &str) {
+        self.lookup_and_emit(lint, None, msg);
+    }
+
     /// Merge the lints specified by any lint attributes into the
     /// current lint context, call the provided function, then reset the
     /// lints in effect to their previous state.
     fn with_lint_attrs<F>(&mut self,
-                          attrs: &[hir::Attribute],
-                          f: F) where
-        F: FnOnce(&mut Context),
+                          attrs: &[ast::Attribute],
+                          f: F)
+        where F: FnOnce(&mut Self),
     {
         // Parse all of the lint attributes, and then add them all to the
         // current dictionary of lint information. Along the way, keep a history
@@ -467,14 +479,15 @@ impl<'a, 'tcx> Context<'a, 'tcx> {
         for result in gather_attrs(attrs) {
             let v = match result {
                 Err(span) => {
-                    self.tcx.sess.span_err(span, "malformed lint attribute");
+                    span_err!(self.sess(), span, E0452,
+                              "malformed lint attribute");
                     continue;
                 }
                 Ok((lint_name, level, span)) => {
-                    match self.lints.find_lint(&lint_name, &self.tcx.sess, Some(span)) {
+                    match self.lints().find_lint(&lint_name, &self.sess(), Some(span)) {
                         Ok(lint_id) => vec![(lint_id, level, span)],
                         Err(FindLintError::NotFound) => {
-                            match self.lints.lint_groups.get(&lint_name[..]) {
+                            match self.lints().lint_groups.get(&lint_name[..]) {
                                 Some(&(ref v, _)) => v.iter()
                                                       .map(|lint_id: &LintId|
                                                            (*lint_id, level, span))
@@ -493,35 +506,82 @@ impl<'a, 'tcx> Context<'a, 'tcx> {
             };
 
             for (lint_id, level, span) in v {
-                let now = self.lints.get_level_source(lint_id).0;
+                let now = self.lints().get_level_source(lint_id).0;
                 if now == Forbid && level != Forbid {
                     let lint_name = lint_id.as_str();
-                    self.tcx.sess.span_err(span,
-                                           &format!("{}({}) overruled by outer forbid({})",
-                                                   level.as_str(), lint_name,
-                                                   lint_name));
+                    span_err!(self.sess(), span, E0453,
+                              "{}({}) overruled by outer forbid({})",
+                              level.as_str(), lint_name,
+                              lint_name);
                 } else if now != level {
-                    let src = self.lints.get_level_source(lint_id).1;
-                    self.level_stack.push((lint_id, (now, src)));
+                    let src = self.lints().get_level_source(lint_id).1;
+                    self.level_stack().push((lint_id, (now, src)));
                     pushed += 1;
-                    self.lints.set_level(lint_id, (level, Node(span)));
+                    self.mut_lints().set_level(lint_id, (level, Node(span)));
                 }
             }
         }
 
-        run_lints!(self, enter_lint_attrs, attrs);
+        self.enter_attrs(attrs);
         f(self);
-        run_lints!(self, exit_lint_attrs, attrs);
+        self.exit_attrs(attrs);
 
         // rollback
         for _ in 0..pushed {
-            let (lint, lvlsrc) = self.level_stack.pop().unwrap();
-            self.lints.set_level(lint, lvlsrc);
+            let (lint, lvlsrc) = self.level_stack().pop().unwrap();
+            self.mut_lints().set_level(lint, lvlsrc);
+        }
+    }
+}
+
+
+impl<'a> EarlyContext<'a> {
+    fn new(sess: &'a Session,
+           krate: &'a ast::Crate) -> EarlyContext<'a> {
+        // We want to own the lint store, so move it out of the session. Remember
+        // to put it back later...
+        let lint_store = mem::replace(&mut *sess.lint_store.borrow_mut(),
+                                      LintStore::new());
+        EarlyContext {
+            sess: sess,
+            krate: krate,
+            lints: lint_store,
+            level_stack: vec![],
+        }
+    }
+
+    fn visit_ids<F>(&mut self, f: F)
+        where F: FnOnce(&mut ast_util::IdVisitor<EarlyContext>)
+    {
+        let mut v = ast_util::IdVisitor {
+            operation: self,
+            pass_through_items: false,
+            visited_outermost: false,
+        };
+        f(&mut v);
+    }
+}
+
+impl<'a, 'tcx> LateContext<'a, 'tcx> {
+    fn new(tcx: &'a ty::ctxt<'tcx>,
+           krate: &'a hir::Crate,
+           exported_items: &'a ExportedItems) -> LateContext<'a, 'tcx> {
+        // We want to own the lint store, so move it out of the session.
+        let lint_store = mem::replace(&mut *tcx.sess.lint_store.borrow_mut(),
+                                      LintStore::new());
+
+        LateContext {
+            tcx: tcx,
+            krate: krate,
+            exported_items: exported_items,
+            lints: lint_store,
+            level_stack: vec![],
+            node_levels: RefCell::new(FnvHashMap()),
         }
     }
 
-    fn visit_ids<F>(&mut self, f: F) where
-        F: FnOnce(&mut util::IdVisitor<Context>)
+    fn visit_ids<F>(&mut self, f: F)
+        where F: FnOnce(&mut util::IdVisitor<LateContext>)
     {
         let mut v = util::IdVisitor {
             operation: self,
@@ -532,158 +592,376 @@ impl<'a, 'tcx> Context<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
+impl<'a, 'tcx> LintContext for LateContext<'a, 'tcx> {
+    /// Get the overall compiler `Session` object.
+    fn sess(&self) -> &Session {
+        &self.tcx.sess
+    }
+
+    fn lints(&self) -> &LintStore {
+        &self.lints
+    }
+
+    fn mut_lints(&mut self) -> &mut LintStore {
+        &mut self.lints
+    }
+
+    fn level_stack(&mut self) -> &mut Vec<(LintId, LevelSource)> {
+        &mut self.level_stack
+    }
+
+    fn enter_attrs(&mut self, attrs: &[ast::Attribute]) {
+        run_lints!(self, enter_lint_attrs, late_passes, attrs);
+    }
+
+    fn exit_attrs(&mut self, attrs: &[ast::Attribute]) {
+        run_lints!(self, exit_lint_attrs, late_passes, attrs);
+    }
+}
+
+impl<'a> LintContext for EarlyContext<'a> {
+    /// Get the overall compiler `Session` object.
+    fn sess(&self) -> &Session {
+        &self.sess
+    }
+
+    fn lints(&self) -> &LintStore {
+        &self.lints
+    }
+
+    fn mut_lints(&mut self) -> &mut LintStore {
+        &mut self.lints
+    }
+
+    fn level_stack(&mut self) -> &mut Vec<(LintId, LevelSource)> {
+        &mut self.level_stack
+    }
+
+    fn enter_attrs(&mut self, attrs: &[ast::Attribute]) {
+        run_lints!(self, enter_lint_attrs, early_passes, attrs);
+    }
+
+    fn exit_attrs(&mut self, attrs: &[ast::Attribute]) {
+        run_lints!(self, exit_lint_attrs, early_passes, attrs);
+    }
+}
+
+impl<'a, 'tcx, 'v> hir_visit::Visitor<'v> for LateContext<'a, 'tcx> {
     fn visit_item(&mut self, it: &hir::Item) {
         self.with_lint_attrs(&it.attrs, |cx| {
-            run_lints!(cx, check_item, it);
+            run_lints!(cx, check_item, late_passes, it);
             cx.visit_ids(|v| v.visit_item(it));
-            visit::walk_item(cx, it);
+            hir_visit::walk_item(cx, it);
         })
     }
 
     fn visit_foreign_item(&mut self, it: &hir::ForeignItem) {
         self.with_lint_attrs(&it.attrs, |cx| {
-            run_lints!(cx, check_foreign_item, it);
-            visit::walk_foreign_item(cx, it);
+            run_lints!(cx, check_foreign_item, late_passes, it);
+            hir_visit::walk_foreign_item(cx, it);
         })
     }
 
     fn visit_pat(&mut self, p: &hir::Pat) {
-        run_lints!(self, check_pat, p);
-        visit::walk_pat(self, p);
+        run_lints!(self, check_pat, late_passes, p);
+        hir_visit::walk_pat(self, p);
     }
 
     fn visit_expr(&mut self, e: &hir::Expr) {
-        run_lints!(self, check_expr, e);
-        visit::walk_expr(self, e);
+        run_lints!(self, check_expr, late_passes, e);
+        hir_visit::walk_expr(self, e);
     }
 
     fn visit_stmt(&mut self, s: &hir::Stmt) {
-        run_lints!(self, check_stmt, s);
-        visit::walk_stmt(self, s);
+        run_lints!(self, check_stmt, late_passes, s);
+        hir_visit::walk_stmt(self, s);
     }
 
-    fn visit_fn(&mut self, fk: FnKind<'v>, decl: &'v hir::FnDecl,
+    fn visit_fn(&mut self, fk: hir_visit::FnKind<'v>, decl: &'v hir::FnDecl,
                 body: &'v hir::Block, span: Span, id: ast::NodeId) {
-        run_lints!(self, check_fn, fk, decl, body, span, id);
-        visit::walk_fn(self, fk, decl, body, span);
+        run_lints!(self, check_fn, late_passes, fk, decl, body, span, id);
+        hir_visit::walk_fn(self, fk, decl, body, span);
     }
 
-    fn visit_struct_def(&mut self,
-                        s: &hir::StructDef,
-                        ident: ast::Ident,
+    fn visit_variant_data(&mut self,
+                        s: &hir::VariantData,
+                        name: ast::Name,
                         g: &hir::Generics,
-                        id: ast::NodeId) {
-        run_lints!(self, check_struct_def, s, ident, g, id);
-        visit::walk_struct_def(self, s);
-        run_lints!(self, check_struct_def_post, s, ident, g, id);
+                        item_id: ast::NodeId,
+                        _: Span) {
+        run_lints!(self, check_struct_def, late_passes, s, name, g, item_id);
+        hir_visit::walk_struct_def(self, s);
+        run_lints!(self, check_struct_def_post, late_passes, s, name, g, item_id);
     }
 
     fn visit_struct_field(&mut self, s: &hir::StructField) {
         self.with_lint_attrs(&s.node.attrs, |cx| {
-            run_lints!(cx, check_struct_field, s);
-            visit::walk_struct_field(cx, s);
+            run_lints!(cx, check_struct_field, late_passes, s);
+            hir_visit::walk_struct_field(cx, s);
         })
     }
 
-    fn visit_variant(&mut self, v: &hir::Variant, g: &hir::Generics) {
+    fn visit_variant(&mut self, v: &hir::Variant, g: &hir::Generics, item_id: ast::NodeId) {
         self.with_lint_attrs(&v.node.attrs, |cx| {
-            run_lints!(cx, check_variant, v, g);
-            visit::walk_variant(cx, v, g);
-            run_lints!(cx, check_variant_post, v, g);
+            run_lints!(cx, check_variant, late_passes, v, g);
+            hir_visit::walk_variant(cx, v, g, item_id);
+            run_lints!(cx, check_variant_post, late_passes, v, g);
         })
     }
 
     fn visit_ty(&mut self, t: &hir::Ty) {
-        run_lints!(self, check_ty, t);
-        visit::walk_ty(self, t);
+        run_lints!(self, check_ty, late_passes, t);
+        hir_visit::walk_ty(self, t);
     }
 
-    fn visit_ident(&mut self, sp: Span, id: ast::Ident) {
-        run_lints!(self, check_ident, sp, id);
+    fn visit_name(&mut self, sp: Span, name: ast::Name) {
+        run_lints!(self, check_name, late_passes, sp, name);
     }
 
     fn visit_mod(&mut self, m: &hir::Mod, s: Span, n: ast::NodeId) {
-        run_lints!(self, check_mod, m, s, n);
-        visit::walk_mod(self, m);
+        run_lints!(self, check_mod, late_passes, m, s, n);
+        hir_visit::walk_mod(self, m);
     }
 
     fn visit_local(&mut self, l: &hir::Local) {
-        run_lints!(self, check_local, l);
-        visit::walk_local(self, l);
+        run_lints!(self, check_local, late_passes, l);
+        hir_visit::walk_local(self, l);
     }
 
     fn visit_block(&mut self, b: &hir::Block) {
-        run_lints!(self, check_block, b);
-        visit::walk_block(self, b);
+        run_lints!(self, check_block, late_passes, b);
+        hir_visit::walk_block(self, b);
     }
 
     fn visit_arm(&mut self, a: &hir::Arm) {
-        run_lints!(self, check_arm, a);
-        visit::walk_arm(self, a);
+        run_lints!(self, check_arm, late_passes, a);
+        hir_visit::walk_arm(self, a);
     }
 
     fn visit_decl(&mut self, d: &hir::Decl) {
-        run_lints!(self, check_decl, d);
-        visit::walk_decl(self, d);
+        run_lints!(self, check_decl, late_passes, d);
+        hir_visit::walk_decl(self, d);
     }
 
     fn visit_expr_post(&mut self, e: &hir::Expr) {
-        run_lints!(self, check_expr_post, e);
+        run_lints!(self, check_expr_post, late_passes, e);
     }
 
     fn visit_generics(&mut self, g: &hir::Generics) {
-        run_lints!(self, check_generics, g);
-        visit::walk_generics(self, g);
+        run_lints!(self, check_generics, late_passes, g);
+        hir_visit::walk_generics(self, g);
     }
 
     fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
         self.with_lint_attrs(&trait_item.attrs, |cx| {
-            run_lints!(cx, check_trait_item, trait_item);
+            run_lints!(cx, check_trait_item, late_passes, trait_item);
             cx.visit_ids(|v| v.visit_trait_item(trait_item));
-            visit::walk_trait_item(cx, trait_item);
+            hir_visit::walk_trait_item(cx, trait_item);
         });
     }
 
     fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
         self.with_lint_attrs(&impl_item.attrs, |cx| {
-            run_lints!(cx, check_impl_item, impl_item);
+            run_lints!(cx, check_impl_item, late_passes, impl_item);
             cx.visit_ids(|v| v.visit_impl_item(impl_item));
-            visit::walk_impl_item(cx, impl_item);
+            hir_visit::walk_impl_item(cx, impl_item);
         });
     }
 
-    fn visit_opt_lifetime_ref(&mut self, sp: Span, lt: &Option<hir::Lifetime>) {
-        run_lints!(self, check_opt_lifetime_ref, sp, lt);
-    }
-
-    fn visit_lifetime_ref(&mut self, lt: &hir::Lifetime) {
-        run_lints!(self, check_lifetime_ref, lt);
+    fn visit_lifetime(&mut self, lt: &hir::Lifetime) {
+        run_lints!(self, check_lifetime, late_passes, lt);
     }
 
     fn visit_lifetime_def(&mut self, lt: &hir::LifetimeDef) {
-        run_lints!(self, check_lifetime_def, lt);
+        run_lints!(self, check_lifetime_def, late_passes, lt);
     }
 
     fn visit_explicit_self(&mut self, es: &hir::ExplicitSelf) {
-        run_lints!(self, check_explicit_self, es);
-        visit::walk_explicit_self(self, es);
+        run_lints!(self, check_explicit_self, late_passes, es);
+        hir_visit::walk_explicit_self(self, es);
     }
 
     fn visit_path(&mut self, p: &hir::Path, id: ast::NodeId) {
-        run_lints!(self, check_path, p, id);
-        visit::walk_path(self, p);
+        run_lints!(self, check_path, late_passes, p, id);
+        hir_visit::walk_path(self, p);
+    }
+
+    fn visit_path_list_item(&mut self, prefix: &hir::Path, item: &hir::PathListItem) {
+        run_lints!(self, check_path_list_item, late_passes, item);
+        hir_visit::walk_path_list_item(self, prefix, item);
     }
 
-    fn visit_attribute(&mut self, attr: &hir::Attribute) {
-        run_lints!(self, check_attribute, attr);
+    fn visit_attribute(&mut self, attr: &ast::Attribute) {
+        run_lints!(self, check_attribute, late_passes, attr);
+    }
+}
+
+impl<'a, 'v> ast_visit::Visitor<'v> for EarlyContext<'a> {
+    fn visit_item(&mut self, it: &ast::Item) {
+        self.with_lint_attrs(&it.attrs, |cx| {
+            run_lints!(cx, check_item, early_passes, it);
+            cx.visit_ids(|v| v.visit_item(it));
+            ast_visit::walk_item(cx, it);
+        })
+    }
+
+    fn visit_foreign_item(&mut self, it: &ast::ForeignItem) {
+        self.with_lint_attrs(&it.attrs, |cx| {
+            run_lints!(cx, check_foreign_item, early_passes, it);
+            ast_visit::walk_foreign_item(cx, it);
+        })
+    }
+
+    fn visit_pat(&mut self, p: &ast::Pat) {
+        run_lints!(self, check_pat, early_passes, p);
+        ast_visit::walk_pat(self, p);
+    }
+
+    fn visit_expr(&mut self, e: &ast::Expr) {
+        run_lints!(self, check_expr, early_passes, e);
+        ast_visit::walk_expr(self, e);
+    }
+
+    fn visit_stmt(&mut self, s: &ast::Stmt) {
+        run_lints!(self, check_stmt, early_passes, s);
+        ast_visit::walk_stmt(self, s);
+    }
+
+    fn visit_fn(&mut self, fk: ast_visit::FnKind<'v>, decl: &'v ast::FnDecl,
+                body: &'v ast::Block, span: Span, id: ast::NodeId) {
+        run_lints!(self, check_fn, early_passes, fk, decl, body, span, id);
+        ast_visit::walk_fn(self, fk, decl, body, span);
+    }
+
+    fn visit_variant_data(&mut self,
+                        s: &ast::VariantData,
+                        ident: ast::Ident,
+                        g: &ast::Generics,
+                        item_id: ast::NodeId,
+                        _: Span) {
+        run_lints!(self, check_struct_def, early_passes, s, ident, g, item_id);
+        ast_visit::walk_struct_def(self, s);
+        run_lints!(self, check_struct_def_post, early_passes, s, ident, g, item_id);
+    }
+
+    fn visit_struct_field(&mut self, s: &ast::StructField) {
+        self.with_lint_attrs(&s.node.attrs, |cx| {
+            run_lints!(cx, check_struct_field, early_passes, s);
+            ast_visit::walk_struct_field(cx, s);
+        })
+    }
+
+    fn visit_variant(&mut self, v: &ast::Variant, g: &ast::Generics, item_id: ast::NodeId) {
+        self.with_lint_attrs(&v.node.attrs, |cx| {
+            run_lints!(cx, check_variant, early_passes, v, g);
+            ast_visit::walk_variant(cx, v, g, item_id);
+            run_lints!(cx, check_variant_post, early_passes, v, g);
+        })
+    }
+
+    fn visit_ty(&mut self, t: &ast::Ty) {
+        run_lints!(self, check_ty, early_passes, t);
+        ast_visit::walk_ty(self, t);
+    }
+
+    fn visit_ident(&mut self, sp: Span, id: ast::Ident) {
+        run_lints!(self, check_ident, early_passes, sp, id);
+    }
+
+    fn visit_mod(&mut self, m: &ast::Mod, s: Span, n: ast::NodeId) {
+        run_lints!(self, check_mod, early_passes, m, s, n);
+        ast_visit::walk_mod(self, m);
+    }
+
+    fn visit_local(&mut self, l: &ast::Local) {
+        run_lints!(self, check_local, early_passes, l);
+        ast_visit::walk_local(self, l);
+    }
+
+    fn visit_block(&mut self, b: &ast::Block) {
+        run_lints!(self, check_block, early_passes, b);
+        ast_visit::walk_block(self, b);
+    }
+
+    fn visit_arm(&mut self, a: &ast::Arm) {
+        run_lints!(self, check_arm, early_passes, a);
+        ast_visit::walk_arm(self, a);
+    }
+
+    fn visit_decl(&mut self, d: &ast::Decl) {
+        run_lints!(self, check_decl, early_passes, d);
+        ast_visit::walk_decl(self, d);
+    }
+
+    fn visit_expr_post(&mut self, e: &ast::Expr) {
+        run_lints!(self, check_expr_post, early_passes, e);
+    }
+
+    fn visit_generics(&mut self, g: &ast::Generics) {
+        run_lints!(self, check_generics, early_passes, g);
+        ast_visit::walk_generics(self, g);
+    }
+
+    fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
+        self.with_lint_attrs(&trait_item.attrs, |cx| {
+            run_lints!(cx, check_trait_item, early_passes, trait_item);
+            cx.visit_ids(|v| v.visit_trait_item(trait_item));
+            ast_visit::walk_trait_item(cx, trait_item);
+        });
+    }
+
+    fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) {
+        self.with_lint_attrs(&impl_item.attrs, |cx| {
+            run_lints!(cx, check_impl_item, early_passes, impl_item);
+            cx.visit_ids(|v| v.visit_impl_item(impl_item));
+            ast_visit::walk_impl_item(cx, impl_item);
+        });
+    }
+
+    fn visit_lifetime(&mut self, lt: &ast::Lifetime) {
+        run_lints!(self, check_lifetime, early_passes, lt);
+    }
+
+    fn visit_lifetime_def(&mut self, lt: &ast::LifetimeDef) {
+        run_lints!(self, check_lifetime_def, early_passes, lt);
+    }
+
+    fn visit_explicit_self(&mut self, es: &ast::ExplicitSelf) {
+        run_lints!(self, check_explicit_self, early_passes, es);
+        ast_visit::walk_explicit_self(self, es);
+    }
+
+    fn visit_path(&mut self, p: &ast::Path, id: ast::NodeId) {
+        run_lints!(self, check_path, early_passes, p, id);
+        ast_visit::walk_path(self, p);
+    }
+
+    fn visit_path_list_item(&mut self, prefix: &ast::Path, item: &ast::PathListItem) {
+        run_lints!(self, check_path_list_item, early_passes, item);
+        ast_visit::walk_path_list_item(self, prefix, item);
+    }
+
+    fn visit_attribute(&mut self, attr: &ast::Attribute) {
+        run_lints!(self, check_attribute, early_passes, attr);
     }
 }
 
 // Output any lints that were previously added to the session.
-impl<'a, 'tcx> IdVisitingOperation for Context<'a, 'tcx> {
+impl<'a, 'tcx> IdVisitingOperation for LateContext<'a, 'tcx> {
+    fn visit_id(&mut self, id: ast::NodeId) {
+        match self.sess().lints.borrow_mut().remove(&id) {
+            None => {}
+            Some(lints) => {
+                for (lint_id, span, msg) in lints {
+                    self.span_lint(lint_id.lint, span, &msg[..])
+                }
+            }
+        }
+    }
+}
+impl<'a> IdVisitingOperation for EarlyContext<'a> {
     fn visit_id(&mut self, id: ast::NodeId) {
-        match self.tcx.sess.lints.borrow_mut().remove(&id) {
+        match self.sess.lints.borrow_mut().remove(&id) {
             None => {}
             Some(lints) => {
                 for (lint_id, span, msg) in lints {
@@ -694,7 +972,7 @@ impl<'a, 'tcx> IdVisitingOperation for Context<'a, 'tcx> {
     }
 }
 
-// This lint pass is defined here because it touches parts of the `Context`
+// This lint pass is defined here because it touches parts of the `LateContext`
 // that we don't want to expose. It records the lint level at certain AST
 // nodes, so that the variant size difference check in trans can call
 // `raw_emit_lint`.
@@ -705,8 +983,10 @@ impl LintPass for GatherNodeLevels {
     fn get_lints(&self) -> LintArray {
         lint_array!()
     }
+}
 
-    fn check_item(&mut self, cx: &Context, it: &hir::Item) {
+impl LateLintPass for GatherNodeLevels {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         match it.node {
             hir::ItemEnum(..) => {
                 let lint_id = LintId::of(builtin::VARIANT_SIZE_DIFFERENCES);
@@ -731,21 +1011,21 @@ pub fn check_crate(tcx: &ty::ctxt,
                    krate: &hir::Crate,
                    exported_items: &ExportedItems) {
 
-    let mut cx = Context::new(tcx, krate, exported_items);
+    let mut cx = LateContext::new(tcx, krate, exported_items);
 
     // Visit the whole crate.
     cx.with_lint_attrs(&krate.attrs, |cx| {
         cx.visit_id(ast::CRATE_NODE_ID);
         cx.visit_ids(|v| {
             v.visited_outermost = true;
-            visit::walk_crate(v, krate);
+            hir_visit::walk_crate(v, krate);
         });
 
         // since the root module isn't visited as an item (because it isn't an
         // item), warn for it here.
-        run_lints!(cx, check_crate, krate);
+        run_lints!(cx, check_crate, late_passes, krate);
 
-        visit::walk_crate(cx, krate);
+        hir_visit::walk_crate(cx, krate);
     });
 
     // If we missed any lints added to the session, then there's a bug somewhere
@@ -760,3 +1040,35 @@ pub fn check_crate(tcx: &ty::ctxt,
 
     *tcx.node_lint_levels.borrow_mut() = cx.node_levels.into_inner();
 }
+
+pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) {
+    let mut cx = EarlyContext::new(sess, krate);
+
+    // Visit the whole crate.
+    cx.with_lint_attrs(&krate.attrs, |cx| {
+        cx.visit_id(ast::CRATE_NODE_ID);
+        cx.visit_ids(|v| {
+            v.visited_outermost = true;
+            ast_visit::walk_crate(v, krate);
+        });
+
+        // since the root module isn't visited as an item (because it isn't an
+        // item), warn for it here.
+        run_lints!(cx, check_crate, early_passes, krate);
+
+        ast_visit::walk_crate(cx, krate);
+    });
+
+    // Put the lint store back in the session.
+    mem::replace(&mut *sess.lint_store.borrow_mut(), cx.lints);
+
+    // If we missed any lints added to the session, then there's a bug somewhere
+    // in the iteration code.
+    for (_, v) in sess.lints.borrow().iter() {
+        for &(lint, span, ref msg) in v {
+            sess.span_bug(span,
+                          &format!("unprocessed lint {}: {}",
+                                   lint.as_str(), *msg))
+        }
+    }
+}
index 2b3a6c6e287f9e0912b84a0304b284e19c76434a..14c11af6f3863293f4f4e51dee855bad2bf3ef2a 100644 (file)
@@ -35,11 +35,13 @@ use std::hash;
 use std::ascii::AsciiExt;
 use syntax::codemap::Span;
 use rustc_front::visit::FnKind;
+use syntax::visit as ast_visit;
 use syntax::ast;
 use rustc_front::hir;
 
-pub use lint::context::{Context, LintStore, raw_emit_lint, check_crate, gather_attrs,
-                        gather_attrs_from_hir, GatherNodeLevels};
+pub use lint::context::{LateContext, EarlyContext, LintContext, LintStore,
+                        raw_emit_lint, check_crate, check_ast_crate, gather_attrs,
+                        GatherNodeLevels};
 
 /// Specification of a single lint.
 #[derive(Copy, Clone, Debug)]
@@ -87,7 +89,6 @@ macro_rules! lint_initializer {
 /// Declare a static item of type `&'static Lint`.
 #[macro_export]
 macro_rules! declare_lint {
-    // FIXME(#14660): deduplicate
     (pub $name:ident, $level:ident, $desc:expr) => (
         pub static $name: &'static ::rustc::lint::Lint
             = &lint_initializer!($name, $level, $desc);
@@ -109,14 +110,6 @@ macro_rules! lint_array { ($( $lint:expr ),*) => (
 
 pub type LintArray = &'static [&'static &'static Lint];
 
-/// Trait for types providing lint checks.
-///
-/// Each `check` method checks a single syntax node, and should not
-/// invoke methods recursively (unlike `Visitor`). By default they
-/// do nothing.
-//
-// FIXME: eliminate the duplication with `Visitor`. But this also
-// contains a few lint-specific methods with no equivalent in `Visitor`.
 pub trait LintPass {
     /// Get descriptions of the lints this `LintPass` object can emit.
     ///
@@ -125,51 +118,104 @@ pub trait LintPass {
     /// parts of the compiler. If you want enforced access restrictions for your
     /// `Lint`, make it a private `static` item in its own module.
     fn get_lints(&self) -> LintArray;
+}
+
 
-    fn check_crate(&mut self, _: &Context, _: &hir::Crate) { }
-    fn check_ident(&mut self, _: &Context, _: Span, _: ast::Ident) { }
-    fn check_mod(&mut self, _: &Context, _: &hir::Mod, _: Span, _: ast::NodeId) { }
-    fn check_foreign_item(&mut self, _: &Context, _: &hir::ForeignItem) { }
-    fn check_item(&mut self, _: &Context, _: &hir::Item) { }
-    fn check_local(&mut self, _: &Context, _: &hir::Local) { }
-    fn check_block(&mut self, _: &Context, _: &hir::Block) { }
-    fn check_stmt(&mut self, _: &Context, _: &hir::Stmt) { }
-    fn check_arm(&mut self, _: &Context, _: &hir::Arm) { }
-    fn check_pat(&mut self, _: &Context, _: &hir::Pat) { }
-    fn check_decl(&mut self, _: &Context, _: &hir::Decl) { }
-    fn check_expr(&mut self, _: &Context, _: &hir::Expr) { }
-    fn check_expr_post(&mut self, _: &Context, _: &hir::Expr) { }
-    fn check_ty(&mut self, _: &Context, _: &hir::Ty) { }
-    fn check_generics(&mut self, _: &Context, _: &hir::Generics) { }
-    fn check_fn(&mut self, _: &Context,
+/// Trait for types providing lint checks.
+///
+/// Each `check` method checks a single syntax node, and should not
+/// invoke methods recursively (unlike `Visitor`). By default they
+/// do nothing.
+//
+// FIXME: eliminate the duplication with `Visitor`. But this also
+// contains a few lint-specific methods with no equivalent in `Visitor`.
+pub trait LateLintPass: LintPass {
+    fn check_name(&mut self, _: &LateContext, _: Span, _: ast::Name) { }
+    fn check_crate(&mut self, _: &LateContext, _: &hir::Crate) { }
+    fn check_mod(&mut self, _: &LateContext, _: &hir::Mod, _: Span, _: ast::NodeId) { }
+    fn check_foreign_item(&mut self, _: &LateContext, _: &hir::ForeignItem) { }
+    fn check_item(&mut self, _: &LateContext, _: &hir::Item) { }
+    fn check_local(&mut self, _: &LateContext, _: &hir::Local) { }
+    fn check_block(&mut self, _: &LateContext, _: &hir::Block) { }
+    fn check_stmt(&mut self, _: &LateContext, _: &hir::Stmt) { }
+    fn check_arm(&mut self, _: &LateContext, _: &hir::Arm) { }
+    fn check_pat(&mut self, _: &LateContext, _: &hir::Pat) { }
+    fn check_decl(&mut self, _: &LateContext, _: &hir::Decl) { }
+    fn check_expr(&mut self, _: &LateContext, _: &hir::Expr) { }
+    fn check_expr_post(&mut self, _: &LateContext, _: &hir::Expr) { }
+    fn check_ty(&mut self, _: &LateContext, _: &hir::Ty) { }
+    fn check_generics(&mut self, _: &LateContext, _: &hir::Generics) { }
+    fn check_fn(&mut self, _: &LateContext,
         _: FnKind, _: &hir::FnDecl, _: &hir::Block, _: Span, _: ast::NodeId) { }
-    fn check_trait_item(&mut self, _: &Context, _: &hir::TraitItem) { }
-    fn check_impl_item(&mut self, _: &Context, _: &hir::ImplItem) { }
-    fn check_struct_def(&mut self, _: &Context,
-        _: &hir::StructDef, _: ast::Ident, _: &hir::Generics, _: ast::NodeId) { }
-    fn check_struct_def_post(&mut self, _: &Context,
-        _: &hir::StructDef, _: ast::Ident, _: &hir::Generics, _: ast::NodeId) { }
-    fn check_struct_field(&mut self, _: &Context, _: &hir::StructField) { }
-    fn check_variant(&mut self, _: &Context, _: &hir::Variant, _: &hir::Generics) { }
-    fn check_variant_post(&mut self, _: &Context, _: &hir::Variant, _: &hir::Generics) { }
-    fn check_opt_lifetime_ref(&mut self, _: &Context, _: Span, _: &Option<hir::Lifetime>) { }
-    fn check_lifetime_ref(&mut self, _: &Context, _: &hir::Lifetime) { }
-    fn check_lifetime_def(&mut self, _: &Context, _: &hir::LifetimeDef) { }
-    fn check_explicit_self(&mut self, _: &Context, _: &hir::ExplicitSelf) { }
-    fn check_mac(&mut self, _: &Context, _: &ast::Mac) { }
-    fn check_path(&mut self, _: &Context, _: &hir::Path, _: ast::NodeId) { }
-    fn check_attribute(&mut self, _: &Context, _: &hir::Attribute) { }
+    fn check_trait_item(&mut self, _: &LateContext, _: &hir::TraitItem) { }
+    fn check_impl_item(&mut self, _: &LateContext, _: &hir::ImplItem) { }
+    fn check_struct_def(&mut self, _: &LateContext,
+        _: &hir::VariantData, _: ast::Name, _: &hir::Generics, _: ast::NodeId) { }
+    fn check_struct_def_post(&mut self, _: &LateContext,
+        _: &hir::VariantData, _: ast::Name, _: &hir::Generics, _: ast::NodeId) { }
+    fn check_struct_field(&mut self, _: &LateContext, _: &hir::StructField) { }
+    fn check_variant(&mut self, _: &LateContext, _: &hir::Variant, _: &hir::Generics) { }
+    fn check_variant_post(&mut self, _: &LateContext, _: &hir::Variant, _: &hir::Generics) { }
+    fn check_lifetime(&mut self, _: &LateContext, _: &hir::Lifetime) { }
+    fn check_lifetime_def(&mut self, _: &LateContext, _: &hir::LifetimeDef) { }
+    fn check_explicit_self(&mut self, _: &LateContext, _: &hir::ExplicitSelf) { }
+    fn check_path(&mut self, _: &LateContext, _: &hir::Path, _: ast::NodeId) { }
+    fn check_path_list_item(&mut self, _: &LateContext, _: &hir::PathListItem) { }
+    fn check_attribute(&mut self, _: &LateContext, _: &ast::Attribute) { }
+
+    /// Called when entering a syntax node that can have lint attributes such
+    /// as `#[allow(...)]`. Called with *all* the attributes of that node.
+    fn enter_lint_attrs(&mut self, _: &LateContext, _: &[ast::Attribute]) { }
+
+    /// Counterpart to `enter_lint_attrs`.
+    fn exit_lint_attrs(&mut self, _: &LateContext, _: &[ast::Attribute]) { }
+}
+
+pub trait EarlyLintPass: LintPass {
+    fn check_ident(&mut self, _: &EarlyContext, _: Span, _: ast::Ident) { }
+    fn check_crate(&mut self, _: &EarlyContext, _: &ast::Crate) { }
+    fn check_mod(&mut self, _: &EarlyContext, _: &ast::Mod, _: Span, _: ast::NodeId) { }
+    fn check_foreign_item(&mut self, _: &EarlyContext, _: &ast::ForeignItem) { }
+    fn check_item(&mut self, _: &EarlyContext, _: &ast::Item) { }
+    fn check_local(&mut self, _: &EarlyContext, _: &ast::Local) { }
+    fn check_block(&mut self, _: &EarlyContext, _: &ast::Block) { }
+    fn check_stmt(&mut self, _: &EarlyContext, _: &ast::Stmt) { }
+    fn check_arm(&mut self, _: &EarlyContext, _: &ast::Arm) { }
+    fn check_pat(&mut self, _: &EarlyContext, _: &ast::Pat) { }
+    fn check_decl(&mut self, _: &EarlyContext, _: &ast::Decl) { }
+    fn check_expr(&mut self, _: &EarlyContext, _: &ast::Expr) { }
+    fn check_expr_post(&mut self, _: &EarlyContext, _: &ast::Expr) { }
+    fn check_ty(&mut self, _: &EarlyContext, _: &ast::Ty) { }
+    fn check_generics(&mut self, _: &EarlyContext, _: &ast::Generics) { }
+    fn check_fn(&mut self, _: &EarlyContext,
+        _: ast_visit::FnKind, _: &ast::FnDecl, _: &ast::Block, _: Span, _: ast::NodeId) { }
+    fn check_trait_item(&mut self, _: &EarlyContext, _: &ast::TraitItem) { }
+    fn check_impl_item(&mut self, _: &EarlyContext, _: &ast::ImplItem) { }
+    fn check_struct_def(&mut self, _: &EarlyContext,
+        _: &ast::VariantData, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { }
+    fn check_struct_def_post(&mut self, _: &EarlyContext,
+        _: &ast::VariantData, _: ast::Ident, _: &ast::Generics, _: ast::NodeId) { }
+    fn check_struct_field(&mut self, _: &EarlyContext, _: &ast::StructField) { }
+    fn check_variant(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { }
+    fn check_variant_post(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { }
+    fn check_lifetime(&mut self, _: &EarlyContext, _: &ast::Lifetime) { }
+    fn check_lifetime_def(&mut self, _: &EarlyContext, _: &ast::LifetimeDef) { }
+    fn check_explicit_self(&mut self, _: &EarlyContext, _: &ast::ExplicitSelf) { }
+    fn check_path(&mut self, _: &EarlyContext, _: &ast::Path, _: ast::NodeId) { }
+    fn check_path_list_item(&mut self, _: &EarlyContext, _: &ast::PathListItem) { }
+    fn check_attribute(&mut self, _: &EarlyContext, _: &ast::Attribute) { }
 
     /// Called when entering a syntax node that can have lint attributes such
     /// as `#[allow(...)]`. Called with *all* the attributes of that node.
-    fn enter_lint_attrs(&mut self, _: &Context, _: &[hir::Attribute]) { }
+    fn enter_lint_attrs(&mut self, _: &EarlyContext, _: &[ast::Attribute]) { }
 
     /// Counterpart to `enter_lint_attrs`.
-    fn exit_lint_attrs(&mut self, _: &Context, _: &[hir::Attribute]) { }
+    fn exit_lint_attrs(&mut self, _: &EarlyContext, _: &[ast::Attribute]) { }
 }
 
 /// A lint pass boxed up as a trait object.
-pub type LintPassObject = Box<LintPass + 'static>;
+pub type EarlyLintPassObject = Box<EarlyLintPass + 'static>;
+pub type LateLintPassObject = Box<LateLintPass + 'static>;
 
 /// Identifies a lint known to the compiler.
 #[derive(Clone, Copy)]
index 0fb55bd7907667cfc99a144ca285b20201beb734..a4fee5b7aa805f063835a603459fed7b8dd9b3fe 100644 (file)
@@ -43,9 +43,15 @@ pub const tag_items_data_parent_item: usize = 0x28;
 
 pub const tag_items_data_item_is_tuple_struct_ctor: usize = 0x29;
 
-pub const tag_index: usize = 0x2a;
+pub const tag_items_closure_kind: usize = 0x2a;
+pub const tag_items_closure_ty: usize = 0x2b;
+pub const tag_def_key: usize = 0x2c;
 
-// GAP 0x2b, 0x2c, 0x2d, 0x2e
+// GAP 0x2d 0x2e
+
+pub const tag_index: usize = 0x110; // top-level only
+pub const tag_xref_index: usize = 0x111; // top-level only
+pub const tag_xref_data: usize = 0x112; // top-level only
 
 pub const tag_meta_item_name_value: usize = 0x2f;
 
@@ -74,8 +80,6 @@ pub const tag_crate_dep_crate_name: usize = 0x36;
 pub const tag_crate_dep_hash: usize = 0x37;
 pub const tag_crate_dep_explicitly_linked: usize = 0x38; // top-level only
 
-pub const tag_mod_impl: usize = 0x39;
-
 pub const tag_item_trait_item: usize = 0x3a;
 
 pub const tag_item_trait_ref: usize = 0x3b;
@@ -89,7 +93,6 @@ pub const tag_path_len: usize = 0x3e;
 pub const tag_path_elem_mod: usize = 0x3f;
 pub const tag_path_elem_name: usize = 0x40;
 pub const tag_item_field: usize = 0x41;
-pub const tag_item_field_origin: usize = 0x42;
 
 pub const tag_item_variances: usize = 0x43;
 /*
@@ -119,29 +122,20 @@ enum_from_u32! {
 
         tag_tree = 0x51,
 
-        tag_id_range = 0x52,
-
+        // GAP 0x52
         tag_table = 0x53,
         // GAP 0x54, 0x55
         tag_table_def = 0x56,
         tag_table_node_type = 0x57,
         tag_table_item_subst = 0x58,
         tag_table_freevars = 0x59,
-        tag_table_tcache = 0x5a,
-        tag_table_param_defs = 0x5b,
-        tag_table_mutbl = 0x5c,
-        tag_table_last_use = 0x5d,
-        tag_table_spill = 0x5e,
+        // GAP 0x5a, 0x5b, 0x5c, 0x5d, 0x5e
         tag_table_method_map = 0x5f,
-        tag_table_vtable_map = 0x60,
+        // GAP 0x60
         tag_table_adjustments = 0x61,
-        tag_table_moves_map = 0x62,
-        tag_table_capture_map = 0x63,
-        tag_table_closure_tys = 0x64,
-        tag_table_closure_kinds = 0x65,
+        // GAP 0x62, 0x63, 0x64, 0x65
         tag_table_upvar_capture_map = 0x66,
-        tag_table_capture_modes = 0x67,
-        // GAP 0x68
+        // GAP 0x67, 0x68
         tag_table_const_qualif = 0x69,
         tag_table_cast_kinds = 0x6a,
     }
@@ -149,10 +143,6 @@ enum_from_u32! {
 
 pub const tag_item_trait_item_sort: usize = 0x70;
 
-pub const tag_item_trait_parent_sort: usize = 0x71;
-
-pub const tag_item_impl_type_basename: usize = 0x72;
-
 pub const tag_crate_triple: usize = 0x105; // top-level only
 
 pub const tag_dylib_dependency_formats: usize = 0x106; // top-level only
@@ -162,33 +152,27 @@ pub const tag_dylib_dependency_formats: usize = 0x106; // top-level only
 // tag_lang_items
 // - tag_lang_items_item
 //   - tag_lang_items_item_id: u32
-//   - tag_lang_items_item_node_id: u32
+//   - tag_lang_items_item_index: u32
 
 pub const tag_lang_items: usize = 0x107; // top-level only
 pub const tag_lang_items_item: usize = 0x73;
 pub const tag_lang_items_item_id: usize = 0x74;
-pub const tag_lang_items_item_node_id: usize = 0x75;
+pub const tag_lang_items_item_index: usize = 0x75;
 pub const tag_lang_items_missing: usize = 0x76;
 
 pub const tag_item_unnamed_field: usize = 0x77;
 pub const tag_items_data_item_visibility: usize = 0x78;
-
-pub const tag_item_method_tps: usize = 0x79;
-pub const tag_item_method_fty: usize = 0x7a;
-
+pub const tag_items_data_item_inherent_impl: usize = 0x79;
+// GAP 0x7a
 pub const tag_mod_child: usize = 0x7b;
 pub const tag_misc_info: usize = 0x108; // top-level only
 pub const tag_misc_info_crate_items: usize = 0x7c;
 
-pub const tag_item_method_provided_source: usize = 0x7d;
-pub const tag_item_impl_vtables: usize = 0x7e;
-
 pub const tag_impls: usize = 0x109; // top-level only
-pub const tag_impls_impl: usize = 0x7f;
-pub const tag_impls_impl_trait_def_id: usize = 0x8d;
+pub const tag_impls_trait: usize = 0x7d;
+pub const tag_impls_trait_impl: usize = 0x7e;
 
-pub const tag_items_data_item_inherent_impl: usize = 0x80;
-pub const tag_items_data_item_extension_impl: usize = 0x81;
+// GAP 0x7f, 0x80, 0x81
 
 pub const tag_native_libraries: usize = 0x10a; // top-level only
 pub const tag_native_libraries_lib: usize = 0x82;
@@ -215,10 +199,10 @@ pub struct LinkMeta {
 
 pub const tag_struct_fields: usize = 0x10d; // top-level only
 pub const tag_struct_field: usize = 0x8a;
-pub const tag_struct_field_id: usize = 0x8b;
 
+pub const tag_items_data_item_struct_ctor: usize = 0x8b;
 pub const tag_attribute_is_sugared_doc: usize = 0x8c;
-
+// GAP 0x8d
 pub const tag_items_data_region: usize = 0x8e;
 
 pub const tag_region_param_def: usize = 0x8f;
@@ -232,9 +216,9 @@ pub const tag_type_param_def: usize = 0x94;
 pub const tag_item_generics: usize = 0x95;
 pub const tag_method_ty_generics: usize = 0x96;
 
-pub const tag_predicate: usize = 0x97;
-pub const tag_predicate_space: usize = 0x98;
-pub const tag_predicate_data: usize = 0x99;
+pub const tag_type_predicate: usize = 0x97;
+pub const tag_self_predicate: usize = 0x98;
+pub const tag_fn_predicate: usize = 0x99;
 
 pub const tag_unsafety: usize = 0x9a;
 
@@ -259,3 +243,11 @@ pub const tag_defaulted_trait: usize = 0xa4;
 pub const tag_impl_coerce_unsized_kind: usize = 0xa5;
 
 pub const tag_items_data_item_constness: usize = 0xa6;
+
+pub const tag_rustc_version: usize = 0x10f;
+pub fn rustc_version() -> String {
+    format!(
+        "rustc {}",
+        option_env!("CFG_VERSION").unwrap_or("unknown version")
+    )
+}
index 5ac84578369d2fc2736475c7506a2fb4797a441b..6c81562f7b2912e892111c98954d6526ba75c9be 100644 (file)
@@ -15,6 +15,7 @@
 use back::svh::Svh;
 use session::{config, Session};
 use session::search_paths::PathKind;
+use metadata::common::rustc_version;
 use metadata::cstore;
 use metadata::cstore::{CStore, CrateSource, MetadataBlob};
 use metadata::decoder;
@@ -33,13 +34,11 @@ use syntax::abi;
 use syntax::codemap::{self, Span, mk_sp, Pos};
 use syntax::parse;
 use syntax::attr;
+use syntax::attr::AttrMetaMethods;
 use syntax::parse::token::InternedString;
 use syntax::util::small_vector::SmallVector;
 use rustc_front::visit;
 use rustc_front::hir;
-use rustc_front::attr as attr_front;
-use rustc_front::attr::AttrMetaMethods;
-use rustc_front::lowering::unlower_attribute;
 use log;
 
 pub struct LocalCrateReader<'a, 'b:'a> {
@@ -79,10 +78,9 @@ fn dump_crates(cstore: &CStore) {
 fn should_link(i: &ast::Item) -> bool {
     !attr::contains_name(&i.attrs, "no_link")
 }
-
 // Dup for the hir
 fn should_link_hir(i: &hir::Item) -> bool {
-    !attr_front::contains_name(&i.attrs, "no_link")
+    !attr::contains_name(&i.attrs, "no_link")
 }
 
 struct CrateInfo {
@@ -122,8 +120,8 @@ fn register_native_lib(sess: &Session,
     if name.is_empty() {
         match span {
             Some(span) => {
-                sess.span_err(span, "#[link(name = \"\")] given with \
-                                     empty name");
+                span_err!(sess, span, E0454,
+                          "#[link(name = \"\")] given with empty name");
             }
             None => {
                 sess.err("empty library name given via `-l`");
@@ -135,7 +133,10 @@ fn register_native_lib(sess: &Session,
     if kind == cstore::NativeFramework && !is_osx {
         let msg = "native frameworks are only available on OSX targets";
         match span {
-            Some(span) => sess.span_err(span, msg),
+            Some(span) => {
+                span_err!(sess, span, E0455,
+                          "{}", msg)
+            }
             None => sess.err(msg),
         }
     }
@@ -201,17 +202,17 @@ impl<'a> CrateReader<'a> {
         match i.node {
             hir::ItemExternCrate(ref path_opt) => {
                 debug!("resolving extern crate stmt. ident: {} path_opt: {:?}",
-                       i.ident, path_opt);
+                       i.name, path_opt);
                 let name = match *path_opt {
                     Some(name) => {
                         validate_crate_name(Some(self.sess), &name.as_str(),
                                             Some(i.span));
                         name.to_string()
                     }
-                    None => i.ident.to_string(),
+                    None => i.name.to_string(),
                 };
                 Some(CrateInfo {
-                    ident: i.ident.to_string(),
+                    ident: i.name.to_string(),
                     name: name,
                     id: i.id,
                     should_link: should_link_hir(i),
@@ -270,6 +271,24 @@ impl<'a> CrateReader<'a> {
         return ret;
     }
 
+    fn verify_rustc_version(&self,
+                            name: &str,
+                            span: Span,
+                            metadata: &MetadataBlob) {
+        let crate_rustc_version = decoder::crate_rustc_version(metadata.as_slice());
+        if crate_rustc_version != Some(rustc_version()) {
+            span_err!(self.sess, span, E0514,
+                      "the crate `{}` has been compiled with {}, which is \
+                       incompatible with this version of rustc",
+                      name,
+                      crate_rustc_version
+                          .as_ref().map(|s|&**s)
+                          .unwrap_or("an old version of rustc")
+            );
+            self.sess.abort_if_errors();
+        }
+    }
+
     fn register_crate(&mut self,
                       root: &Option<CratePaths>,
                       ident: &str,
@@ -279,6 +298,8 @@ impl<'a> CrateReader<'a> {
                       explicitly_linked: bool)
                       -> (ast::CrateNum, Rc<cstore::crate_metadata>,
                           cstore::CrateSource) {
+        self.verify_rustc_version(name, span, &lib.metadata);
+
         // Claim this crate number and cache it
         let cnum = self.next_crate_num;
         self.next_crate_num += 1;
@@ -304,7 +325,9 @@ impl<'a> CrateReader<'a> {
         let cmeta = Rc::new(cstore::crate_metadata {
             name: name.to_string(),
             local_path: RefCell::new(SmallVector::zero()),
+            local_def_path: RefCell::new(vec![]),
             index: decoder::load_index(metadata.as_slice()),
+            xref_index: decoder::load_xrefs(metadata.as_slice()),
             data: metadata,
             cnum_map: RefCell::new(cnum_map),
             cnum: cnum,
@@ -329,7 +352,7 @@ impl<'a> CrateReader<'a> {
         let attrs = decoder::get_crate_attributes(data);
         for attr in &attrs {
             if &attr.name()[..] == "staged_api" {
-                match attr.node.value.node { hir::MetaWord(_) => return true, _ => (/*pass*/) }
+                match attr.node.value.node { ast::MetaWord(_) => return true, _ => (/*pass*/) }
             }
         }
 
@@ -481,9 +504,15 @@ impl<'a> CrateReader<'a> {
                 };
                 let span = mk_sp(lo, p.last_span.hi);
                 p.abort_if_errors();
+
+                // Mark the attrs as used
+                for attr in &attrs {
+                    attr::mark_used(attr);
+                }
+
                 macros.push(ast::MacroDef {
-                    ident: name.ident(),
-                    attrs: attrs.iter().map(|a| unlower_attribute(a)).collect(),
+                    ident: ast::Ident::with_empty_ctxt(name),
+                    attrs: attrs,
                     id: ast::DUMMY_NODE_ID,
                     span: span,
                     imported_from: Some(item.ident),
@@ -517,20 +546,21 @@ impl<'a> CrateReader<'a> {
                                   name,
                                   config::host_triple(),
                                   self.sess.opts.target_triple);
-            self.sess.span_err(span, &message[..]);
+            span_err!(self.sess, span, E0456, "{}", &message[..]);
             self.sess.abort_if_errors();
         }
 
-        let registrar = decoder::get_plugin_registrar_fn(ekrate.metadata.as_slice())
+        let registrar =
+            decoder::get_plugin_registrar_fn(ekrate.metadata.as_slice())
             .map(|id| decoder::get_symbol_from_buf(ekrate.metadata.as_slice(), id));
 
         match (ekrate.dylib.as_ref(), registrar) {
             (Some(dylib), Some(reg)) => Some((dylib.to_path_buf(), reg)),
             (None, Some(_)) => {
-                let message = format!("plugin `{}` only found in rlib format, \
-                                       but must be available in dylib format",
-                                       name);
-                self.sess.span_err(span, &message[..]);
+                span_err!(self.sess, span, E0457,
+                          "plugin `{}` only found in rlib format, but must be available \
+                           in dylib format",
+                          name);
                 // No need to abort because the loading code will just ignore this
                 // empty dylib.
                 None
@@ -724,6 +754,9 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
                                                               i.span,
                                                               PathKind::Crate,
                                                               true);
+                        let def_id = self.ast_map.local_def_id(i.id);
+                        let def_path = self.ast_map.def_path(def_id);
+                        cmeta.update_local_def_path(def_path);
                         self.ast_map.with_path(i.id, |path| {
                             cmeta.update_local_path(path)
                         });
@@ -763,7 +796,8 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
                 Some("dylib") => cstore::NativeUnknown,
                 Some("framework") => cstore::NativeFramework,
                 Some(k) => {
-                    self.sess.span_err(m.span, &format!("unknown kind: `{}`", k));
+                    span_err!(self.sess, m.span, E0458,
+                              "unknown kind: `{}`", k);
                     cstore::NativeUnknown
                 }
                 None => cstore::NativeUnknown
@@ -774,8 +808,8 @@ impl<'a, 'b> LocalCrateReader<'a, 'b> {
             let n = match n {
                 Some(n) => n,
                 None => {
-                    self.sess.span_err(m.span, "#[link(...)] specified without \
-                                                `name = \"foo\"`");
+                    span_err!(self.sess, m.span, E0459,
+                              "#[link(...)] specified without `name = \"foo\"`");
                     InternedString::new("foo")
                 }
             };
index e1cb9bd0e77cf60db4317ad998cae8d564355d64..e04df51dc6862dce539c49b2510fa798a1ecc74f 100644 (file)
@@ -14,14 +14,14 @@ use front::map as ast_map;
 use metadata::cstore;
 use metadata::decoder;
 use metadata::inline::InlinedItem;
-use middle::def_id::DefId;
+use middle::def_id::{DefId, DefIndex};
 use middle::lang_items;
 use middle::ty;
 use util::nodemap::FnvHashMap;
 
 use std::rc::Rc;
 use syntax::ast;
-use rustc_front::attr;
+use syntax::attr;
 use rustc_front::hir;
 
 #[derive(Copy, Clone)]
@@ -33,7 +33,7 @@ pub struct MethodInfo {
 
 pub fn get_symbol(cstore: &cstore::CStore, def: DefId) -> String {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_symbol(&cdata, def.node)
+    decoder::get_symbol(&cdata, def.index)
 }
 
 /// Iterates over all the language items in the given crate.
@@ -41,7 +41,7 @@ pub fn each_lang_item<F>(cstore: &cstore::CStore,
                          cnum: ast::CrateNum,
                          f: F)
                          -> bool where
-    F: FnMut(ast::NodeId, usize) -> bool,
+    F: FnMut(DefIndex, usize) -> bool,
 {
     let crate_data = cstore.get_crate_data(cnum);
     decoder::each_lang_item(&*crate_data, f)
@@ -59,7 +59,7 @@ pub fn each_child_of_item<F>(cstore: &cstore::CStore,
     };
     decoder::each_child_of_item(cstore.intr.clone(),
                                 &*crate_data,
-                                def_id.node,
+                                def_id.index,
                                 get_crate_data,
                                 callback)
 }
@@ -83,7 +83,7 @@ pub fn each_top_level_item_of_crate<F>(cstore: &cstore::CStore,
 pub fn get_item_path(tcx: &ty::ctxt, def: DefId) -> Vec<ast_map::PathElem> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    let path = decoder::get_item_path(&*cdata, def.node);
+    let path = decoder::get_item_path(&*cdata, def.index);
 
     cdata.with_local_path(|cpath| {
         let mut r = Vec::with_capacity(cpath.len() + path.len());
@@ -96,7 +96,7 @@ pub fn get_item_path(tcx: &ty::ctxt, def: DefId) -> Vec<ast_map::PathElem> {
 pub fn get_item_name(tcx: &ty::ctxt, def: DefId) -> ast::Name {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_item_name(&cstore.intr, &cdata, def.node)
+    decoder::get_item_name(&cstore.intr, &cdata, def.index)
 }
 
 pub enum FoundAst<'ast> {
@@ -113,14 +113,14 @@ pub fn maybe_get_item_ast<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId,
                                 -> FoundAst<'tcx> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::maybe_get_item_ast(&*cdata, tcx, def.node, decode_inlined_item)
+    decoder::maybe_get_item_ast(&*cdata, tcx, def.index, decode_inlined_item)
 }
 
 /// Returns information about the given implementation.
 pub fn get_impl_items(cstore: &cstore::CStore, impl_def_id: DefId)
                       -> Vec<ty::ImplOrTraitItemId> {
     let cdata = cstore.get_crate_data(impl_def_id.krate);
-    decoder::get_impl_items(&*cdata, impl_def_id.node)
+    decoder::get_impl_items(&*cdata, impl_def_id.index)
 }
 
 pub fn get_impl_or_trait_item<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId)
@@ -128,7 +128,7 @@ pub fn get_impl_or_trait_item<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId)
     let cdata = tcx.sess.cstore.get_crate_data(def.krate);
     decoder::get_impl_or_trait_item(tcx.sess.cstore.intr.clone(),
                                     &*cdata,
-                                    def.node,
+                                    def.index,
                                     tcx)
 }
 
@@ -136,24 +136,24 @@ pub fn get_trait_name(cstore: &cstore::CStore, def: DefId) -> ast::Name {
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_trait_name(cstore.intr.clone(),
                             &*cdata,
-                            def.node)
+                            def.index)
 }
 
 pub fn is_static_method(cstore: &cstore::CStore, def: DefId) -> bool {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::is_static_method(&*cdata, def.node)
+    decoder::is_static_method(&*cdata, def.index)
 }
 
 pub fn get_trait_item_def_ids(cstore: &cstore::CStore, def: DefId)
                               -> Vec<ty::ImplOrTraitItemId> {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_trait_item_def_ids(&*cdata, def.node)
+    decoder::get_trait_item_def_ids(&*cdata, def.index)
 }
 
 pub fn get_item_variances(cstore: &cstore::CStore,
                           def: DefId) -> ty::ItemVariances {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_item_variances(&*cdata, def.node)
+    decoder::get_item_variances(&*cdata, def.index)
 }
 
 pub fn get_provided_trait_methods<'tcx>(tcx: &ty::ctxt<'tcx>,
@@ -161,43 +161,37 @@ pub fn get_provided_trait_methods<'tcx>(tcx: &ty::ctxt<'tcx>,
                                         -> Vec<Rc<ty::Method<'tcx>>> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_provided_trait_methods(cstore.intr.clone(), &*cdata, def.node, tcx)
+    decoder::get_provided_trait_methods(cstore.intr.clone(), &*cdata, def.index, tcx)
 }
 
 pub fn get_associated_consts<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId)
                                    -> Vec<Rc<ty::AssociatedConst<'tcx>>> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_associated_consts(cstore.intr.clone(), &*cdata, def.node, tcx)
-}
-
-pub fn get_type_name_if_impl(cstore: &cstore::CStore, def: DefId)
-                          -> Option<ast::Name> {
-    let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_type_name_if_impl(&*cdata, def.node)
+    decoder::get_associated_consts(cstore.intr.clone(), &*cdata, def.index, tcx)
 }
 
 pub fn get_methods_if_impl(cstore: &cstore::CStore,
                                   def: DefId)
                                -> Option<Vec<MethodInfo> > {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_methods_if_impl(cstore.intr.clone(), &*cdata, def.node)
+    decoder::get_methods_if_impl(cstore.intr.clone(), &*cdata, def.index)
 }
 
 pub fn get_item_attrs(cstore: &cstore::CStore,
                       def_id: DefId)
-                      -> Vec<hir::Attribute> {
+                      -> Vec<ast::Attribute> {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::get_item_attrs(&*cdata, def_id.node)
+    decoder::get_item_attrs(&*cdata, def_id.index)
 }
 
 pub fn get_struct_field_names(cstore: &cstore::CStore, def: DefId) -> Vec<ast::Name> {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_struct_field_names(&cstore.intr, &*cdata, def.node)
+    decoder::get_struct_field_names(&cstore.intr, &*cdata, def.index)
 }
 
-pub fn get_struct_field_attrs(cstore: &cstore::CStore, def: DefId) -> FnvHashMap<ast::NodeId,
-        Vec<hir::Attribute>> {
+pub fn get_struct_field_attrs(cstore: &cstore::CStore, def: DefId)
+                              -> FnvHashMap<DefId, Vec<ast::Attribute>> {
     let cdata = cstore.get_crate_data(def.krate);
     decoder::get_struct_field_attrs(&*cdata)
 }
@@ -207,19 +201,19 @@ pub fn get_type<'tcx>(tcx: &ty::ctxt<'tcx>,
                       -> ty::TypeScheme<'tcx> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_type(&*cdata, def.node, tcx)
+    decoder::get_type(&*cdata, def.index, tcx)
 }
 
 pub fn get_trait_def<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId) -> ty::TraitDef<'tcx> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_trait_def(&*cdata, def.node, tcx)
+    decoder::get_trait_def(&*cdata, def.index, tcx)
 }
 
 pub fn get_adt_def<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_adt_def(&cstore.intr, &*cdata, def.node, tcx)
+    decoder::get_adt_def(&cstore.intr, &*cdata, def.index, tcx)
 }
 
 pub fn get_predicates<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId)
@@ -227,7 +221,7 @@ pub fn get_predicates<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId)
 {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_predicates(&*cdata, def.node, tcx)
+    decoder::get_predicates(&*cdata, def.index, tcx)
 }
 
 pub fn get_super_predicates<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId)
@@ -235,7 +229,7 @@ pub fn get_super_predicates<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId)
 {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_super_predicates(&*cdata, def.node, tcx)
+    decoder::get_super_predicates(&*cdata, def.index, tcx)
 }
 
 pub fn get_impl_polarity<'tcx>(tcx: &ty::ctxt<'tcx>,
@@ -244,7 +238,7 @@ pub fn get_impl_polarity<'tcx>(tcx: &ty::ctxt<'tcx>,
 {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_impl_polarity(&*cdata, def.node)
+    decoder::get_impl_polarity(&*cdata, def.index)
 }
 
 pub fn get_custom_coerce_unsized_kind<'tcx>(
@@ -254,7 +248,7 @@ pub fn get_custom_coerce_unsized_kind<'tcx>(
 {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_custom_coerce_unsized_kind(&*cdata, def.node)
+    decoder::get_custom_coerce_unsized_kind(&*cdata, def.index)
 }
 
 // Given a def_id for an impl, return the trait it implements,
@@ -264,7 +258,7 @@ pub fn get_impl_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
                             -> Option<ty::TraitRef<'tcx>> {
     let cstore = &tcx.sess.cstore;
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_impl_trait(&*cdata, def.node, tcx)
+    decoder::get_impl_trait(&*cdata, def.index, tcx)
 }
 
 pub fn get_native_libraries(cstore: &cstore::CStore, crate_num: ast::CrateNum)
@@ -279,7 +273,7 @@ pub fn each_inherent_implementation_for_type<F>(cstore: &cstore::CStore,
     F: FnMut(DefId),
 {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::each_inherent_implementation_for_type(&*cdata, def_id.node, callback)
+    decoder::each_inherent_implementation_for_type(&*cdata, def_id.index, callback)
 }
 
 pub fn each_implementation_for_trait<F>(cstore: &cstore::CStore,
@@ -300,7 +294,7 @@ pub fn get_trait_of_item(cstore: &cstore::CStore,
                          tcx: &ty::ctxt)
                          -> Option<DefId> {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::get_trait_of_item(&*cdata, def_id.node, tcx)
+    decoder::get_trait_of_item(&*cdata, def_id.index, tcx)
 }
 
 pub fn get_tuple_struct_definition_if_ctor(cstore: &cstore::CStore,
@@ -308,7 +302,7 @@ pub fn get_tuple_struct_definition_if_ctor(cstore: &cstore::CStore,
     -> Option<DefId>
 {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::get_tuple_struct_definition_if_ctor(&*cdata, def_id.node)
+    decoder::get_tuple_struct_definition_if_ctor(&*cdata, def_id.index)
 }
 
 pub fn get_dylib_dependency_formats(cstore: &cstore::CStore,
@@ -330,7 +324,7 @@ pub fn get_method_arg_names(cstore: &cstore::CStore, did: DefId)
     -> Vec<String>
 {
     let cdata = cstore.get_crate_data(did.krate);
-    decoder::get_method_arg_names(&*cdata, did.node)
+    decoder::get_method_arg_names(&*cdata, did.index)
 }
 
 pub fn get_reachable_ids(cstore: &cstore::CStore, cnum: ast::CrateNum)
@@ -342,24 +336,24 @@ pub fn get_reachable_ids(cstore: &cstore::CStore, cnum: ast::CrateNum)
 
 pub fn is_typedef(cstore: &cstore::CStore, did: DefId) -> bool {
     let cdata = cstore.get_crate_data(did.krate);
-    decoder::is_typedef(&*cdata, did.node)
+    decoder::is_typedef(&*cdata, did.index)
 }
 
 pub fn is_const_fn(cstore: &cstore::CStore, did: DefId) -> bool {
     let cdata = cstore.get_crate_data(did.krate);
-    decoder::is_const_fn(&*cdata, did.node)
+    decoder::is_const_fn(&*cdata, did.index)
 }
 
 pub fn is_impl(cstore: &cstore::CStore, did: DefId) -> bool {
     let cdata = cstore.get_crate_data(did.krate);
-    decoder::is_impl(&*cdata, did.node)
+    decoder::is_impl(&*cdata, did.index)
 }
 
 pub fn get_stability(cstore: &cstore::CStore,
                      def: DefId)
                      -> Option<attr::Stability> {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_stability(&*cdata, def.node)
+    decoder::get_stability(&*cdata, def.index)
 }
 
 pub fn is_staged_api(cstore: &cstore::CStore, krate: ast::CrateNum) -> bool {
@@ -369,21 +363,42 @@ pub fn is_staged_api(cstore: &cstore::CStore, krate: ast::CrateNum) -> bool {
 pub fn get_repr_attrs(cstore: &cstore::CStore, def: DefId)
                       -> Vec<attr::ReprAttr> {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_repr_attrs(&*cdata, def.node)
+    decoder::get_repr_attrs(&*cdata, def.index)
 }
 
 pub fn is_defaulted_trait(cstore: &cstore::CStore, trait_def_id: DefId) -> bool {
     let cdata = cstore.get_crate_data(trait_def_id.krate);
-    decoder::is_defaulted_trait(&*cdata, trait_def_id.node)
+    decoder::is_defaulted_trait(&*cdata, trait_def_id.index)
 }
 
 pub fn is_default_impl(cstore: &cstore::CStore, impl_did: DefId) -> bool {
     let cdata = cstore.get_crate_data(impl_did.krate);
-    decoder::is_default_impl(&*cdata, impl_did.node)
+    decoder::is_default_impl(&*cdata, impl_did.index)
 }
 
 pub fn is_extern_fn(cstore: &cstore::CStore, did: DefId,
                     tcx: &ty::ctxt) -> bool {
     let cdata = cstore.get_crate_data(did.krate);
-    decoder::is_extern_fn(&*cdata, did.node, tcx)
+    decoder::is_extern_fn(&*cdata, did.index, tcx)
+}
+
+pub fn closure_kind<'tcx>(tcx: &ty::ctxt<'tcx>, def_id: DefId) -> ty::ClosureKind {
+    assert!(!def_id.is_local());
+    let cdata = tcx.sess.cstore.get_crate_data(def_id.krate);
+    decoder::closure_kind(&*cdata, def_id.index)
+}
+
+pub fn closure_ty<'tcx>(tcx: &ty::ctxt<'tcx>, def_id: DefId) -> ty::ClosureTy<'tcx> {
+    assert!(!def_id.is_local());
+    let cdata = tcx.sess.cstore.get_crate_data(def_id.krate);
+    decoder::closure_ty(&*cdata, def_id.index, tcx)
+}
+
+pub fn def_path(tcx: &ty::ctxt, def: DefId) -> ast_map::DefPath {
+    let cstore = &tcx.sess.cstore;
+    let cdata = cstore.get_crate_data(def.krate);
+    let path = decoder::def_path(&*cdata, def.index);
+    let local_path = cdata.local_def_path();
+    local_path.into_iter().chain(path).collect()
 }
+
index 42f52b2d20b1b949151ad64c66778983b7a7efb1..873c22c35d855016fc3068ee2e2f3fa7c0bd52cb 100644 (file)
@@ -27,7 +27,7 @@ use std::rc::Rc;
 use std::path::PathBuf;
 use flate::Bytes;
 use syntax::ast;
-use rustc_front::attr;
+use syntax::attr;
 use syntax::codemap;
 use syntax::parse::token;
 use syntax::parse::token::IdentInterner;
@@ -59,13 +59,16 @@ pub struct ImportedFileMap {
 pub struct crate_metadata {
     pub name: String,
     pub local_path: RefCell<SmallVector<ast_map::PathElem>>,
+    pub local_def_path: RefCell<ast_map::DefPath>,
     pub data: MetadataBlob,
     pub cnum_map: RefCell<cnum_map>,
     pub cnum: ast::CrateNum,
     pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
     pub span: codemap::Span,
     pub staged_api: bool,
+
     pub index: index::Index,
+    pub xref_index: index::DenseIndex,
 
     /// Flag if this crate is required by an rlib version of this crate, or in
     /// other words whether it was explicitly linked to. An example of a crate
@@ -109,6 +112,10 @@ pub struct CStore {
     pub intr: Rc<IdentInterner>,
 }
 
+/// Item definitions in the currently-compiled crate would have the CrateNum
+/// LOCAL_CRATE in their DefId.
+pub const LOCAL_CRATE: ast::CrateNum = 0;
+
 impl CStore {
     pub fn new(intr: Rc<IdentInterner>) -> CStore {
         CStore {
@@ -200,7 +207,7 @@ impl CStore {
                 visit(cstore, dep, ordering);
             }
             ordering.push(cnum);
-        };
+        }
         for (&num, _) in self.metas.borrow().iter() {
             visit(self, num, &mut ordering);
         }
@@ -308,6 +315,23 @@ impl crate_metadata {
         }
     }
 
+    pub fn local_def_path(&self) -> ast_map::DefPath {
+        let local_def_path = self.local_def_path.borrow();
+        if local_def_path.is_empty() {
+            let name = ast_map::DefPathData::DetachedCrate(token::intern(&self.name));
+            vec![ast_map::DisambiguatedDefPathData { data: name, disambiguator: 0 }]
+        } else {
+            local_def_path.clone()
+        }
+    }
+
+    pub fn update_local_def_path(&self, candidate: ast_map::DefPath) {
+        let mut local_def_path = self.local_def_path.borrow_mut();
+        if local_def_path.is_empty() || candidate.len() < local_def_path.len() {
+            *local_def_path = candidate;
+        }
+    }
+
     pub fn is_allocator(&self) -> bool {
         let attrs = decoder::get_crate_attributes(self.data());
         attr::contains_name(&attrs, "allocator")
index e2cf50cf30ad0b4a768c510eb25bf12a150f62c6..0780252fc887b8b3c83b1bcbc8a221fd524dad20 100644 (file)
 pub use self::DefLike::*;
 use self::Family::*;
 
-use front::map as ast_map;
-use rustc_front::print::pprust;
+use front::map as hir_map;
 use rustc_front::hir;
 
 use back::svh::Svh;
 use metadata::cstore::crate_metadata;
+use metadata::cstore::LOCAL_CRATE;
 use metadata::common::*;
 use metadata::csearch::MethodInfo;
 use metadata::csearch;
@@ -30,7 +30,7 @@ use metadata::index;
 use metadata::inline::InlinedItem;
 use metadata::tydecode::TyDecoder;
 use middle::def;
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::{DefId, DefIndex};
 use middle::lang_items;
 use middle::subst;
 use middle::ty::{ImplContainer, TraitContainer};
@@ -46,27 +46,28 @@ use std::str;
 use rbml::reader;
 use rbml;
 use serialize::Decodable;
-use rustc_front::attr;
+use syntax::attr;
 use syntax::parse::token::{IdentInterner, special_idents};
 use syntax::parse::token;
 use syntax::ast;
 use syntax::abi;
 use syntax::codemap;
+use syntax::print::pprust;
 use syntax::ptr::P;
 
 
 pub type Cmd<'a> = &'a crate_metadata;
 
 impl crate_metadata {
-    fn get_item(&self, item_id: ast::NodeId) -> Option<rbml::Doc> {
+    fn get_item(&self, item_id: DefIndex) -> Option<rbml::Doc> {
         self.index.lookup_item(self.data(), item_id).map(|pos| {
             reader::doc_at(self.data(), pos as usize).unwrap().doc
         })
     }
 
-    fn lookup_item(&self, item_id: ast::NodeId) -> rbml::Doc {
+    fn lookup_item(&self, item_id: DefIndex) -> rbml::Doc {
         match self.get_item(item_id) {
-            None => panic!("lookup_item: id not found: {}", item_id),
+            None => panic!("lookup_item: id not found: {:?}", item_id),
             Some(d) => d
         }
     }
@@ -74,7 +75,17 @@ impl crate_metadata {
 
 pub fn load_index(data: &[u8]) -> index::Index {
     let index = reader::get_doc(rbml::Doc::new(data), tag_index);
-    index::Index::from_buf(index.data, index.start, index.end)
+    index::Index::from_rbml(index)
+}
+
+pub fn crate_rustc_version(data: &[u8]) -> Option<String> {
+    let doc = rbml::Doc::new(data);
+    reader::maybe_get_doc(doc, tag_rustc_version).map(|s| s.as_str())
+}
+
+pub fn load_xrefs(data: &[u8]) -> index::DenseIndex {
+    let index = reader::get_doc(rbml::Doc::new(data), tag_xref_index);
+    index::DenseIndex::from_buf(index.data, index.start, index.end)
 }
 
 #[derive(Debug, PartialEq)]
@@ -164,7 +175,8 @@ fn item_symbol(item: rbml::Doc) -> String {
 
 fn translated_def_id(cdata: Cmd, d: rbml::Doc) -> DefId {
     let id = reader::doc_as_u64(d);
-    let def_id = DefId { krate: (id >> 32) as u32, node: id as u32 };
+    let index = DefIndex::new((id & 0xFFFF_FFFF) as usize);
+    let def_id = DefId { krate: (id >> 32) as u32, index: index };
     translate_def_id(cdata, def_id)
 }
 
@@ -182,12 +194,6 @@ fn item_def_id(d: rbml::Doc, cdata: Cmd) -> DefId {
     translated_def_id(cdata, reader::get_doc(d, tag_def_id))
 }
 
-fn get_provided_source(d: rbml::Doc, cdata: Cmd) -> Option<DefId> {
-    reader::maybe_get_doc(d, tag_item_method_provided_source).map(|doc| {
-        translated_def_id(cdata, doc)
-    })
-}
-
 fn reexports<'a>(d: rbml::Doc<'a>) -> reader::TaggedDocsIterator<'a> {
     reader::tagged_docs(d, tag_items_data_item_reexport)
 }
@@ -203,26 +209,18 @@ fn variant_disr_val(d: rbml::Doc) -> Option<ty::Disr> {
 fn doc_type<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd) -> Ty<'tcx> {
     let tp = reader::get_doc(doc, tag_items_data_item_type);
     TyDecoder::with_doc(tcx, cdata.cnum, tp,
-                        &mut |_, did| translate_def_id(cdata, did))
+                        &mut |did| translate_def_id(cdata, did))
         .parse_ty()
 }
 
 fn maybe_doc_type<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd) -> Option<Ty<'tcx>> {
     reader::maybe_get_doc(doc, tag_items_data_item_type).map(|tp| {
         TyDecoder::with_doc(tcx, cdata.cnum, tp,
-                            &mut |_, did| translate_def_id(cdata, did))
+                            &mut |did| translate_def_id(cdata, did))
             .parse_ty()
     })
 }
 
-fn doc_method_fty<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>,
-                        cdata: Cmd) -> ty::BareFnTy<'tcx> {
-    let tp = reader::get_doc(doc, tag_item_method_fty);
-    TyDecoder::with_doc(tcx, cdata.cnum, tp,
-                        &mut |_, did| translate_def_id(cdata, did))
-        .parse_bare_fn_ty()
-}
-
 pub fn item_type<'tcx>(_item_id: DefId, item: rbml::Doc,
                        tcx: &ty::ctxt<'tcx>, cdata: Cmd) -> Ty<'tcx> {
     doc_type(item, tcx, cdata)
@@ -231,7 +229,7 @@ pub fn item_type<'tcx>(_item_id: DefId, item: rbml::Doc,
 fn doc_trait_ref<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd)
                        -> ty::TraitRef<'tcx> {
     TyDecoder::with_doc(tcx, cdata.cnum, doc,
-                        &mut |_, did| translate_def_id(cdata, did))
+                        &mut |did| translate_def_id(cdata, did))
         .parse_trait_ref()
 }
 
@@ -241,15 +239,15 @@ fn item_trait_ref<'tcx>(doc: rbml::Doc, tcx: &ty::ctxt<'tcx>, cdata: Cmd)
     doc_trait_ref(tp, tcx, cdata)
 }
 
-fn item_path(item_doc: rbml::Doc) -> Vec<ast_map::PathElem> {
+fn item_path(item_doc: rbml::Doc) -> Vec<hir_map::PathElem> {
     let path_doc = reader::get_doc(item_doc, tag_path);
     reader::docs(path_doc).filter_map(|(tag, elt_doc)| {
         if tag == tag_path_elem_mod {
             let s = elt_doc.as_str_slice();
-            Some(ast_map::PathMod(token::intern(s)))
+            Some(hir_map::PathMod(token::intern(s)))
         } else if tag == tag_path_elem_name {
             let s = elt_doc.as_str_slice();
-            Some(ast_map::PathName(token::intern(s)))
+            Some(hir_map::PathName(token::intern(s)))
         } else {
             // ignore tag_path_len element
             None
@@ -271,11 +269,14 @@ fn item_to_def_like(cdata: Cmd, item: rbml::Doc, did: DefId) -> DefLike {
     match fam {
         Constant  => {
             // Check whether we have an associated const item.
-            if item_sort(item) == Some('C') {
-                DlDef(def::DefAssociatedConst(did))
-            } else {
-                // Regular const item.
-                DlDef(def::DefConst(did))
+            match item_sort(item) {
+                Some('C') | Some('c') => {
+                    DlDef(def::DefAssociatedConst(did))
+                }
+                _ => {
+                    // Regular const item.
+                    DlDef(def::DefConst(did))
+                }
             }
         }
         ImmStatic => DlDef(def::DefStatic(did, false)),
@@ -342,7 +343,7 @@ fn parse_associated_type_names(item_doc: rbml::Doc) -> Vec<ast::Name> {
 }
 
 pub fn get_trait_def<'tcx>(cdata: Cmd,
-                           item_id: ast::NodeId,
+                           item_id: DefIndex,
                            tcx: &ty::ctxt<'tcx>) -> ty::TraitDef<'tcx>
 {
     let item_doc = cdata.lookup_item(item_id);
@@ -365,7 +366,7 @@ pub fn get_trait_def<'tcx>(cdata: Cmd,
 
 pub fn get_adt_def<'tcx>(intr: &IdentInterner,
                          cdata: Cmd,
-                         item_id: ast::NodeId,
+                         item_id: DefIndex,
                          tcx: &ty::ctxt<'tcx>) -> ty::AdtDefMaster<'tcx>
 {
     fn get_enum_variants<'tcx>(intr: &IdentInterner,
@@ -375,7 +376,7 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
         let mut disr_val = 0;
         reader::tagged_docs(doc, tag_items_data_item_variant).map(|p| {
             let did = translated_def_id(cdata, p);
-            let item = cdata.lookup_item(did.node);
+            let item = cdata.lookup_item(did.index);
 
             if let Some(disr) = variant_disr_val(item) {
                 disr_val = disr;
@@ -425,13 +426,22 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
     }
 
     let doc = cdata.lookup_item(item_id);
-    let did = DefId { krate: cdata.cnum, node: item_id };
+    let did = DefId { krate: cdata.cnum, index: item_id };
     let (kind, variants) = match item_family(doc) {
-        Enum => (ty::AdtKind::Enum,
-                 get_enum_variants(intr, cdata, doc, tcx)),
-        Struct => (ty::AdtKind::Struct,
-                   vec![get_struct_variant(intr, cdata, doc, did, tcx)]),
-        _ => tcx.sess.bug("get_adt_def called on a non-ADT")
+        Enum => {
+            (ty::AdtKind::Enum,
+             get_enum_variants(intr, cdata, doc, tcx))
+        }
+        Struct => {
+            let ctor_did =
+                reader::maybe_get_doc(doc, tag_items_data_item_struct_ctor).
+                map_or(did, |ctor_doc| translated_def_id(cdata, ctor_doc));
+            (ty::AdtKind::Struct,
+             vec![get_struct_variant(intr, cdata, doc, ctor_did, tcx)])
+        }
+        _ => tcx.sess.bug(
+            &format!("get_adt_def called on a non-ADT {:?} - {:?}",
+                     item_family(doc), did))
     };
 
     let adt = tcx.intern_adt_def(did, kind, variants);
@@ -445,7 +455,7 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
             // from the ctor.
             debug!("evaluating the ctor-type of {:?}",
                    variant.name);
-            let ctor_ty = get_type(cdata, variant.did.node, tcx).ty;
+            let ctor_ty = get_type(cdata, variant.did.index, tcx).ty;
             debug!("evaluating the ctor-type of {:?}.. {:?}",
                    variant.name,
                    ctor_ty);
@@ -465,7 +475,7 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
         } else {
             for field in &variant.fields {
                 debug!("evaluating the type of {:?}::{:?}", variant.name, field.name);
-                let ty = get_type(cdata, field.did.node, tcx).ty;
+                let ty = get_type(cdata, field.did.index, tcx).ty;
                 field.fulfill_ty(ty);
                 debug!("evaluating the type of {:?}::{:?}: {:?}",
                        variant.name, field.name, ty);
@@ -477,7 +487,7 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
 }
 
 pub fn get_predicates<'tcx>(cdata: Cmd,
-                            item_id: ast::NodeId,
+                            item_id: DefIndex,
                             tcx: &ty::ctxt<'tcx>)
                             -> ty::GenericPredicates<'tcx>
 {
@@ -486,7 +496,7 @@ pub fn get_predicates<'tcx>(cdata: Cmd,
 }
 
 pub fn get_super_predicates<'tcx>(cdata: Cmd,
-                                  item_id: ast::NodeId,
+                                  item_id: DefIndex,
                                   tcx: &ty::ctxt<'tcx>)
                                   -> ty::GenericPredicates<'tcx>
 {
@@ -494,11 +504,11 @@ pub fn get_super_predicates<'tcx>(cdata: Cmd,
     doc_predicates(item_doc, tcx, cdata, tag_item_super_predicates)
 }
 
-pub fn get_type<'tcx>(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt<'tcx>)
+pub fn get_type<'tcx>(cdata: Cmd, id: DefIndex, tcx: &ty::ctxt<'tcx>)
                       -> ty::TypeScheme<'tcx>
 {
     let item_doc = cdata.lookup_item(id);
-    let t = item_type(DefId { krate: cdata.cnum, node: id }, item_doc, tcx,
+    let t = item_type(DefId { krate: cdata.cnum, index: id }, item_doc, tcx,
                       cdata);
     let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics);
     ty::TypeScheme {
@@ -507,7 +517,7 @@ pub fn get_type<'tcx>(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt<'tcx>)
     }
 }
 
-pub fn get_stability(cdata: Cmd, id: ast::NodeId) -> Option<attr::Stability> {
+pub fn get_stability(cdata: Cmd, id: DefIndex) -> Option<attr::Stability> {
     let item = cdata.lookup_item(id);
     reader::maybe_get_doc(item, tag_items_data_item_stability).map(|doc| {
         let mut decoder = reader::Decoder::new(doc);
@@ -515,7 +525,7 @@ pub fn get_stability(cdata: Cmd, id: ast::NodeId) -> Option<attr::Stability> {
     })
 }
 
-pub fn get_repr_attrs(cdata: Cmd, id: ast::NodeId) -> Vec<attr::ReprAttr> {
+pub fn get_repr_attrs(cdata: Cmd, id: DefIndex) -> Vec<attr::ReprAttr> {
     let item = cdata.lookup_item(id);
     match reader::maybe_get_doc(item, tag_items_data_item_repr).map(|doc| {
         let mut decoder = reader::Decoder::new(doc);
@@ -527,7 +537,7 @@ pub fn get_repr_attrs(cdata: Cmd, id: ast::NodeId) -> Vec<attr::ReprAttr> {
 }
 
 pub fn get_impl_polarity<'tcx>(cdata: Cmd,
-                               id: ast::NodeId)
+                               id: DefIndex)
                                -> Option<hir::ImplPolarity>
 {
     let item_doc = cdata.lookup_item(id);
@@ -542,7 +552,7 @@ pub fn get_impl_polarity<'tcx>(cdata: Cmd,
 
 pub fn get_custom_coerce_unsized_kind<'tcx>(
     cdata: Cmd,
-    id: ast::NodeId)
+    id: DefIndex)
     -> Option<ty::adjustment::CustomCoerceUnsized>
 {
     let item_doc = cdata.lookup_item(id);
@@ -553,7 +563,7 @@ pub fn get_custom_coerce_unsized_kind<'tcx>(
 }
 
 pub fn get_impl_trait<'tcx>(cdata: Cmd,
-                            id: ast::NodeId,
+                            id: DefIndex,
                             tcx: &ty::ctxt<'tcx>)
                             -> Option<ty::TraitRef<'tcx>>
 {
@@ -569,12 +579,12 @@ pub fn get_impl_trait<'tcx>(cdata: Cmd,
     }
 }
 
-pub fn get_symbol(cdata: Cmd, id: ast::NodeId) -> String {
+pub fn get_symbol(cdata: Cmd, id: DefIndex) -> String {
     return item_symbol(cdata.lookup_item(id));
 }
 
 /// If you have a crate_metadata, call get_symbol instead
-pub fn get_symbol_from_buf(data: &[u8], id: ast::NodeId) -> String {
+pub fn get_symbol_from_buf(data: &[u8], id: DefIndex) -> String {
     let index = load_index(data);
     let pos = index.lookup_item(data, id).unwrap();
     let doc = reader::doc_at(data, pos as usize).unwrap().doc;
@@ -591,18 +601,17 @@ pub enum DefLike {
 
 /// Iterates over the language items in the given crate.
 pub fn each_lang_item<F>(cdata: Cmd, mut f: F) -> bool where
-    F: FnMut(ast::NodeId, usize) -> bool,
+    F: FnMut(DefIndex, usize) -> bool,
 {
     let root = rbml::Doc::new(cdata.data());
     let lang_items = reader::get_doc(root, tag_lang_items);
     reader::tagged_docs(lang_items, tag_lang_items_item).all(|item_doc| {
         let id_doc = reader::get_doc(item_doc, tag_lang_items_item_id);
         let id = reader::doc_as_u32(id_doc) as usize;
-        let node_id_doc = reader::get_doc(item_doc,
-                                          tag_lang_items_item_node_id);
-        let node_id = reader::doc_as_u32(node_id_doc) as ast::NodeId;
+        let index_doc = reader::get_doc(item_doc, tag_lang_items_item_index);
+        let index = DefIndex::from_u32(reader::doc_as_u32(index_doc));
 
-        f(node_id, id)
+        f(index, id)
     })
 }
 
@@ -631,7 +640,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
         };
 
         // Get the item.
-        match crate_data.get_item(child_def_id.node) {
+        match crate_data.get_item(child_def_id.index) {
             None => {}
             Some(child_item_doc) => {
                 // Hand off the item to the callback.
@@ -649,12 +658,12 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
     for inherent_impl_def_id_doc in reader::tagged_docs(item_doc,
                                                              tag_items_data_item_inherent_impl) {
         let inherent_impl_def_id = item_def_id(inherent_impl_def_id_doc, cdata);
-        if let Some(inherent_impl_doc) = cdata.get_item(inherent_impl_def_id.node) {
+        if let Some(inherent_impl_doc) = cdata.get_item(inherent_impl_def_id.index) {
             for impl_item_def_id_doc in reader::tagged_docs(inherent_impl_doc,
                                                                  tag_item_impl_item) {
                 let impl_item_def_id = item_def_id(impl_item_def_id_doc,
                                                    cdata);
-                if let Some(impl_method_doc) = cdata.get_item(impl_item_def_id.node) {
+                if let Some(impl_method_doc) = cdata.get_item(impl_item_def_id.index) {
                     if let StaticMethod = item_family(impl_method_doc) {
                         // Hand off the static method to the callback.
                         let static_method_name = item_name(&*intr, impl_method_doc);
@@ -690,7 +699,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
         };
 
         // Get the item.
-        if let Some(child_item_doc) = crate_data.get_item(child_def_id.node) {
+        if let Some(child_item_doc) = crate_data.get_item(child_def_id.index) {
             // Hand off the item to the callback.
             let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id);
             // These items have a public visibility because they're part of
@@ -703,7 +712,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
 /// Iterates over each child of the given item.
 pub fn each_child_of_item<F, G>(intr: Rc<IdentInterner>,
                                cdata: Cmd,
-                               id: ast::NodeId,
+                               id: DefIndex,
                                get_crate_data: G,
                                callback: F) where
     F: FnMut(DefLike, ast::Name, hir::Visibility),
@@ -742,34 +751,39 @@ pub fn each_top_level_item_of_crate<F, G>(intr: Rc<IdentInterner>,
                                 callback)
 }
 
-pub fn get_item_path(cdata: Cmd, id: ast::NodeId) -> Vec<ast_map::PathElem> {
+pub fn get_item_path(cdata: Cmd, id: DefIndex) -> Vec<hir_map::PathElem> {
     item_path(cdata.lookup_item(id))
 }
 
-pub fn get_item_name(intr: &IdentInterner, cdata: Cmd, id: ast::NodeId) -> ast::Name {
+pub fn get_item_name(intr: &IdentInterner, cdata: Cmd, id: DefIndex) -> ast::Name {
     item_name(intr, cdata.lookup_item(id))
 }
 
 pub type DecodeInlinedItem<'a> =
     Box<for<'tcx> FnMut(Cmd,
                         &ty::ctxt<'tcx>,
-                        Vec<ast_map::PathElem>,
-                        rbml::Doc)
-                        -> Result<&'tcx InlinedItem, Vec<ast_map::PathElem>> + 'a>;
-
-pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: ast::NodeId,
+                        Vec<hir_map::PathElem>,
+                        hir_map::DefPath,
+                        rbml::Doc,
+                        DefId)
+                        -> Result<&'tcx InlinedItem, (Vec<hir_map::PathElem>,
+                                                      hir_map::DefPath)> + 'a>;
+
+pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: DefIndex,
                                 mut decode_inlined_item: DecodeInlinedItem)
                                 -> csearch::FoundAst<'tcx> {
-    debug!("Looking up item: {}", id);
+    debug!("Looking up item: {:?}", id);
     let item_doc = cdata.lookup_item(id);
+    let item_did = item_def_id(item_doc, cdata);
     let path = item_path(item_doc).split_last().unwrap().1.to_vec();
-    match decode_inlined_item(cdata, tcx, path, item_doc) {
+    let def_path = def_path(cdata, id);
+    match decode_inlined_item(cdata, tcx, path, def_path, item_doc, item_did) {
         Ok(ii) => csearch::FoundAst::Found(ii),
-        Err(path) => {
+        Err((path, def_path)) => {
             match item_parent_item(cdata, item_doc) {
                 Some(did) => {
-                    let parent_item = cdata.lookup_item(did.node);
-                    match decode_inlined_item(cdata, tcx, path, parent_item) {
+                    let parent_item = cdata.lookup_item(did.index);
+                    match decode_inlined_item(cdata, tcx, path, def_path, parent_item, did) {
                         Ok(ii) => csearch::FoundAst::FoundParent(did, ii),
                         Err(_) => csearch::FoundAst::NotFound
                     }
@@ -808,12 +822,12 @@ fn get_explicit_self(item: rbml::Doc) -> ty::ExplicitSelfCategory {
 }
 
 /// Returns the def IDs of all the items in the given implementation.
-pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId)
+pub fn get_impl_items(cdata: Cmd, impl_id: DefIndex)
                       -> Vec<ty::ImplOrTraitItemId> {
     reader::tagged_docs(cdata.lookup_item(impl_id), tag_item_impl_item).map(|doc| {
         let def_id = item_def_id(doc, cdata);
         match item_sort(doc) {
-            Some('C') => ty::ConstTraitItemId(def_id),
+            Some('C') | Some('c') => ty::ConstTraitItemId(def_id),
             Some('r') | Some('p') => ty::MethodTraitItemId(def_id),
             Some('t') => ty::TypeTraitItemId(def_id),
             _ => panic!("unknown impl item sort"),
@@ -823,13 +837,13 @@ pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId)
 
 pub fn get_trait_name(intr: Rc<IdentInterner>,
                       cdata: Cmd,
-                      id: ast::NodeId)
+                      id: DefIndex)
                       -> ast::Name {
     let doc = cdata.lookup_item(id);
     item_name(&*intr, doc)
 }
 
-pub fn is_static_method(cdata: Cmd, id: ast::NodeId) -> bool {
+pub fn is_static_method(cdata: Cmd, id: DefIndex) -> bool {
     let doc = cdata.lookup_item(id);
     match item_sort(doc) {
         Some('r') | Some('p') => {
@@ -841,7 +855,7 @@ pub fn is_static_method(cdata: Cmd, id: ast::NodeId) -> bool {
 
 pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
                                     cdata: Cmd,
-                                    id: ast::NodeId,
+                                    id: DefIndex,
                                     tcx: &ty::ctxt<'tcx>)
                                     -> ty::ImplOrTraitItem<'tcx> {
     let item_doc = cdata.lookup_item(id);
@@ -849,7 +863,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
     let def_id = item_def_id(item_doc, cdata);
 
     let container_id = item_require_parent_item(cdata, item_doc);
-    let container_doc = cdata.lookup_item(container_id.node);
+    let container_doc = cdata.lookup_item(container_id.index);
     let container = match item_family(container_doc) {
         Trait => TraitContainer(container_id),
         _ => ImplContainer(container_id),
@@ -859,24 +873,28 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
     let vis = item_visibility(item_doc);
 
     match item_sort(item_doc) {
-        Some('C') => {
+        sort @ Some('C') | sort @ Some('c') => {
             let ty = doc_type(item_doc, tcx, cdata);
-            let default = get_provided_source(item_doc, cdata);
             ty::ConstTraitItem(Rc::new(ty::AssociatedConst {
                 name: name,
                 ty: ty,
                 vis: vis,
                 def_id: def_id,
                 container: container,
-                default: default,
+                has_value: sort == Some('C')
             }))
         }
         Some('r') | Some('p') => {
             let generics = doc_generics(item_doc, tcx, cdata, tag_method_ty_generics);
             let predicates = doc_predicates(item_doc, tcx, cdata, tag_method_ty_generics);
-            let fty = doc_method_fty(item_doc, tcx, cdata);
+            let ity = tcx.lookup_item_type(def_id).ty;
+            let fty = match ity.sty {
+                ty::TyBareFn(_, fty) => fty.clone(),
+                _ => tcx.sess.bug(&format!(
+                    "the type {:?} of the method {:?} is not a function?",
+                    ity, name))
+            };
             let explicit_self = get_explicit_self(item_doc);
-            let provided_source = get_provided_source(item_doc, cdata);
 
             ty::MethodTraitItem(Rc::new(ty::Method::new(name,
                                                         generics,
@@ -885,8 +903,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
                                                         explicit_self,
                                                         vis,
                                                         def_id,
-                                                        container,
-                                                        provided_source)))
+                                                        container)))
         }
         Some('t') => {
             let ty = maybe_doc_type(item_doc, tcx, cdata);
@@ -902,13 +919,13 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
     }
 }
 
-pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId)
+pub fn get_trait_item_def_ids(cdata: Cmd, id: DefIndex)
                               -> Vec<ty::ImplOrTraitItemId> {
     let item = cdata.lookup_item(id);
     reader::tagged_docs(item, tag_item_trait_item).map(|mth| {
         let def_id = item_def_id(mth, cdata);
         match item_sort(mth) {
-            Some('C') => ty::ConstTraitItemId(def_id),
+            Some('C') | Some('c') => ty::ConstTraitItemId(def_id),
             Some('r') | Some('p') => ty::MethodTraitItemId(def_id),
             Some('t') => ty::TypeTraitItemId(def_id),
             _ => panic!("unknown trait item sort"),
@@ -916,7 +933,7 @@ pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId)
     }).collect()
 }
 
-pub fn get_item_variances(cdata: Cmd, id: ast::NodeId) -> ty::ItemVariances {
+pub fn get_item_variances(cdata: Cmd, id: DefIndex) -> ty::ItemVariances {
     let item_doc = cdata.lookup_item(id);
     let variance_doc = reader::get_doc(item_doc, tag_item_variances);
     let mut decoder = reader::Decoder::new(variance_doc);
@@ -925,19 +942,19 @@ pub fn get_item_variances(cdata: Cmd, id: ast::NodeId) -> ty::ItemVariances {
 
 pub fn get_provided_trait_methods<'tcx>(intr: Rc<IdentInterner>,
                                         cdata: Cmd,
-                                        id: ast::NodeId,
+                                        id: DefIndex,
                                         tcx: &ty::ctxt<'tcx>)
                                         -> Vec<Rc<ty::Method<'tcx>>> {
     let item = cdata.lookup_item(id);
 
     reader::tagged_docs(item, tag_item_trait_item).filter_map(|mth_id| {
         let did = item_def_id(mth_id, cdata);
-        let mth = cdata.lookup_item(did.node);
+        let mth = cdata.lookup_item(did.index);
 
         if item_sort(mth) == Some('p') {
             let trait_item = get_impl_or_trait_item(intr.clone(),
                                                     cdata,
-                                                    did.node,
+                                                    did.index,
                                                     tcx);
             if let ty::MethodTraitItem(ref method) = trait_item {
                 Some((*method).clone())
@@ -952,7 +969,7 @@ pub fn get_provided_trait_methods<'tcx>(intr: Rc<IdentInterner>,
 
 pub fn get_associated_consts<'tcx>(intr: Rc<IdentInterner>,
                                    cdata: Cmd,
-                                   id: ast::NodeId,
+                                   id: DefIndex,
                                    tcx: &ty::ctxt<'tcx>)
                                    -> Vec<Rc<ty::AssociatedConst<'tcx>>> {
     let item = cdata.lookup_item(id);
@@ -960,40 +977,29 @@ pub fn get_associated_consts<'tcx>(intr: Rc<IdentInterner>,
     [tag_item_trait_item, tag_item_impl_item].iter().flat_map(|&tag| {
         reader::tagged_docs(item, tag).filter_map(|ac_id| {
             let did = item_def_id(ac_id, cdata);
-            let ac_doc = cdata.lookup_item(did.node);
-
-            if item_sort(ac_doc) == Some('C') {
-                let trait_item = get_impl_or_trait_item(intr.clone(),
-                                                        cdata,
-                                                        did.node,
-                                                        tcx);
-                if let ty::ConstTraitItem(ref ac) = trait_item {
-                    Some((*ac).clone())
-                } else {
-                    None
+            let ac_doc = cdata.lookup_item(did.index);
+
+            match item_sort(ac_doc) {
+                Some('C') | Some('c') => {
+                    let trait_item = get_impl_or_trait_item(intr.clone(),
+                                                            cdata,
+                                                            did.index,
+                                                            tcx);
+                    if let ty::ConstTraitItem(ref ac) = trait_item {
+                        Some((*ac).clone())
+                    } else {
+                        None
+                    }
                 }
-            } else {
-                None
+                _ => None
             }
         })
     }).collect()
 }
 
-pub fn get_type_name_if_impl(cdata: Cmd,
-                             node_id: ast::NodeId) -> Option<ast::Name> {
-    let item = cdata.lookup_item(node_id);
-    if item_family(item) != Impl {
-        return None;
-    }
-
-    reader::tagged_docs(item, tag_item_impl_type_basename).nth(0).map(|doc| {
-        token::intern(doc.as_str_slice())
-    })
-}
-
 pub fn get_methods_if_impl(intr: Rc<IdentInterner>,
                                   cdata: Cmd,
-                                  node_id: ast::NodeId)
+                                  node_id: DefIndex)
                                -> Option<Vec<MethodInfo> > {
     let item = cdata.lookup_item(node_id);
     if item_family(item) != Impl {
@@ -1010,7 +1016,7 @@ pub fn get_methods_if_impl(intr: Rc<IdentInterner>,
 
     let mut impl_methods = Vec::new();
     for impl_method_id in impl_method_ids {
-        let impl_method_doc = cdata.lookup_item(impl_method_id.node);
+        let impl_method_doc = cdata.lookup_item(impl_method_id.index);
         let family = item_family(impl_method_doc);
         match family {
             StaticMethod | Method => {
@@ -1030,7 +1036,7 @@ pub fn get_methods_if_impl(intr: Rc<IdentInterner>,
 /// If node_id is the constructor of a tuple struct, retrieve the NodeId of
 /// the actual type definition, otherwise, return None
 pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd,
-                                           node_id: ast::NodeId)
+                                           node_id: DefIndex)
     -> Option<DefId>
 {
     let item = cdata.lookup_item(node_id);
@@ -1040,24 +1046,24 @@ pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd,
 }
 
 pub fn get_item_attrs(cdata: Cmd,
-                      orig_node_id: ast::NodeId)
-                      -> Vec<hir::Attribute> {
+                      orig_node_id: DefIndex)
+                      -> Vec<ast::Attribute> {
     // The attributes for a tuple struct are attached to the definition, not the ctor;
     // we assume that someone passing in a tuple struct ctor is actually wanting to
     // look at the definition
     let node_id = get_tuple_struct_definition_if_ctor(cdata, orig_node_id);
-    let node_id = node_id.map(|x| x.node).unwrap_or(orig_node_id);
+    let node_id = node_id.map(|x| x.index).unwrap_or(orig_node_id);
     let item = cdata.lookup_item(node_id);
     get_attributes(item)
 }
 
-pub fn get_struct_field_attrs(cdata: Cmd) -> FnvHashMap<ast::NodeId, Vec<hir::Attribute>> {
+pub fn get_struct_field_attrs(cdata: Cmd) -> FnvHashMap<DefId, Vec<ast::Attribute>> {
     let data = rbml::Doc::new(cdata.data());
     let fields = reader::get_doc(data, tag_struct_fields);
     reader::tagged_docs(fields, tag_struct_field).map(|field| {
-        let id = reader::doc_as_u32(reader::get_doc(field, tag_struct_field_id));
+        let def_id = translated_def_id(cdata, reader::get_doc(field, tag_def_id));
         let attrs = get_attributes(field);
-        (id, attrs)
+        (def_id, attrs)
     }).collect()
 }
 
@@ -1069,7 +1075,7 @@ fn struct_field_family_to_visibility(family: Family) -> hir::Visibility {
     }
 }
 
-pub fn get_struct_field_names(intr: &IdentInterner, cdata: Cmd, id: ast::NodeId)
+pub fn get_struct_field_names(intr: &IdentInterner, cdata: Cmd, id: DefIndex)
     -> Vec<ast::Name> {
     let item = cdata.lookup_item(id);
     reader::tagged_docs(item, tag_item_field).map(|an_item| {
@@ -1079,7 +1085,7 @@ pub fn get_struct_field_names(intr: &IdentInterner, cdata: Cmd, id: ast::NodeId)
     })).collect()
 }
 
-fn get_meta_items(md: rbml::Doc) -> Vec<P<hir::MetaItem>> {
+fn get_meta_items(md: rbml::Doc) -> Vec<P<ast::MetaItem>> {
     reader::tagged_docs(md, tag_meta_item_word).map(|meta_item_doc| {
         let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
         let n = token::intern_and_get_ident(nd.as_str_slice());
@@ -1100,7 +1106,7 @@ fn get_meta_items(md: rbml::Doc) -> Vec<P<hir::MetaItem>> {
     })).collect()
 }
 
-fn get_attributes(md: rbml::Doc) -> Vec<hir::Attribute> {
+fn get_attributes(md: rbml::Doc) -> Vec<ast::Attribute> {
     match reader::maybe_get_doc(md, tag_attributes) {
         Some(attrs_d) => {
             reader::tagged_docs(attrs_d, tag_attribute).map(|attr_doc| {
@@ -1113,9 +1119,9 @@ fn get_attributes(md: rbml::Doc) -> Vec<hir::Attribute> {
                 assert_eq!(meta_items.len(), 1);
                 let meta_item = meta_items.into_iter().nth(0).unwrap();
                 codemap::Spanned {
-                    node: hir::Attribute_ {
+                    node: ast::Attribute_ {
                         id: attr::mk_attr_id(),
-                        style: hir::AttrOuter,
+                        style: ast::AttrStyle::Outer,
                         value: meta_item,
                         is_sugared_doc: is_sugared_doc,
                     },
@@ -1139,7 +1145,7 @@ fn list_crate_attributes(md: rbml::Doc, hash: &Svh,
     write!(out, "\n\n")
 }
 
-pub fn get_crate_attributes(data: &[u8]) -> Vec<hir::Attribute> {
+pub fn get_crate_attributes(data: &[u8]) -> Vec<ast::Attribute> {
     get_attributes(rbml::Doc::new(data))
 }
 
@@ -1227,14 +1233,14 @@ pub fn list_crate_metadata(bytes: &[u8], out: &mut io::Write) -> io::Result<()>
 // crate to the correct local crate number.
 pub fn translate_def_id(cdata: Cmd, did: DefId) -> DefId {
     if did.is_local() {
-        return DefId { krate: cdata.cnum, node: did.node };
+        return DefId { krate: cdata.cnum, index: did.index };
     }
 
     match cdata.cnum_map.borrow().get(&did.krate) {
         Some(&n) => {
             DefId {
                 krate: n,
-                node: did.node,
+                index: did.index,
             }
         }
         None => panic!("didn't find a crate in the cnum_map")
@@ -1245,12 +1251,12 @@ pub fn translate_def_id(cdata: Cmd, did: DefId) -> DefId {
 // for an external crate.
 fn reverse_translate_def_id(cdata: Cmd, did: DefId) -> Option<DefId> {
     if did.krate == cdata.cnum {
-        return Some(DefId { krate: LOCAL_CRATE, node: did.node });
+        return Some(DefId { krate: LOCAL_CRATE, index: did.index });
     }
 
     for (&local, &global) in cdata.cnum_map.borrow().iter() {
         if global == did.krate {
-            return Some(DefId { krate: local, node: did.node });
+            return Some(DefId { krate: local, index: did.index });
         }
     }
 
@@ -1258,7 +1264,7 @@ fn reverse_translate_def_id(cdata: Cmd, did: DefId) -> Option<DefId> {
 }
 
 pub fn each_inherent_implementation_for_type<F>(cdata: Cmd,
-                                                id: ast::NodeId,
+                                                id: DefIndex,
                                                 mut callback: F)
     where F: FnMut(DefId),
 {
@@ -1275,37 +1281,32 @@ pub fn each_implementation_for_trait<F>(cdata: Cmd,
                                         mut callback: F) where
     F: FnMut(DefId),
 {
-    if cdata.cnum == def_id.krate {
-        let item_doc = cdata.lookup_item(def_id.node);
-        for impl_doc in reader::tagged_docs(item_doc, tag_items_data_item_extension_impl) {
-            callback(item_def_id(impl_doc, cdata));
-        }
-        return;
-    }
-
     // Do a reverse lookup beforehand to avoid touching the crate_num
     // hash map in the loop below.
     if let Some(crate_local_did) = reverse_translate_def_id(cdata, def_id) {
         let def_id_u64 = def_to_u64(crate_local_did);
 
         let impls_doc = reader::get_doc(rbml::Doc::new(cdata.data()), tag_impls);
-        for impl_doc in reader::tagged_docs(impls_doc, tag_impls_impl) {
-            let impl_trait = reader::get_doc(impl_doc, tag_impls_impl_trait_def_id);
-            if reader::doc_as_u64(impl_trait) == def_id_u64 {
-                callback(item_def_id(impl_doc, cdata));
+        for trait_doc in reader::tagged_docs(impls_doc, tag_impls_trait) {
+            let trait_def_id = reader::get_doc(trait_doc, tag_def_id);
+            if reader::doc_as_u64(trait_def_id) != def_id_u64 {
+                continue;
+            }
+            for impl_doc in reader::tagged_docs(trait_doc, tag_impls_trait_impl) {
+                callback(translated_def_id(cdata, impl_doc));
             }
         }
     }
 }
 
-pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
+pub fn get_trait_of_item(cdata: Cmd, id: DefIndex, tcx: &ty::ctxt)
                          -> Option<DefId> {
     let item_doc = cdata.lookup_item(id);
     let parent_item_id = match item_parent_item(cdata, item_doc) {
         None => return None,
         Some(item_id) => item_id,
     };
-    let parent_item_doc = cdata.lookup_item(parent_item_id.node);
+    let parent_item_doc = cdata.lookup_item(parent_item_id.index);
     match item_family(parent_item_doc) {
         Trait => Some(item_def_id(parent_item_doc, cdata)),
         Impl | DefaultImpl => {
@@ -1331,13 +1332,13 @@ pub fn get_native_libraries(cdata: Cmd)
     }).collect()
 }
 
-pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
+pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<DefIndex> {
     reader::maybe_get_doc(rbml::Doc::new(data), tag_plugin_registrar_fn)
-        .map(|doc| reader::doc_as_u32(doc))
+        .map(|doc| DefIndex::from_u32(reader::doc_as_u32(doc)))
 }
 
 pub fn each_exported_macro<F>(data: &[u8], intr: &IdentInterner, mut f: F) where
-    F: FnMut(ast::Name, Vec<hir::Attribute>, String) -> bool,
+    F: FnMut(ast::Name, Vec<ast::Attribute>, String) -> bool,
 {
     let macros = reader::get_doc(rbml::Doc::new(data), tag_macro_defs);
     for macro_doc in reader::tagged_docs(macros, tag_macro_def) {
@@ -1385,7 +1386,7 @@ pub fn get_missing_lang_items(cdata: Cmd)
     }).collect()
 }
 
-pub fn get_method_arg_names(cdata: Cmd, id: ast::NodeId) -> Vec<String> {
+pub fn get_method_arg_names(cdata: Cmd, id: DefIndex) -> Vec<String> {
     let method_doc = cdata.lookup_item(id);
     match reader::maybe_get_doc(method_doc, tag_method_argument_names) {
         Some(args_doc) => {
@@ -1403,12 +1404,12 @@ pub fn get_reachable_ids(cdata: Cmd) -> Vec<DefId> {
     reader::tagged_docs(items, tag_reachable_id).map(|doc| {
         DefId {
             krate: cdata.cnum,
-            node: reader::doc_as_u32(doc),
+            index: DefIndex::from_u32(reader::doc_as_u32(doc)),
         }
     }).collect()
 }
 
-pub fn is_typedef(cdata: Cmd, id: ast::NodeId) -> bool {
+pub fn is_typedef(cdata: Cmd, id: DefIndex) -> bool {
     let item_doc = cdata.lookup_item(id);
     match item_family(item_doc) {
         Type => true,
@@ -1416,7 +1417,7 @@ pub fn is_typedef(cdata: Cmd, id: ast::NodeId) -> bool {
     }
 }
 
-pub fn is_const_fn(cdata: Cmd, id: ast::NodeId) -> bool {
+pub fn is_const_fn(cdata: Cmd, id: DefIndex) -> bool {
     let item_doc = cdata.lookup_item(id);
     match fn_constness(item_doc) {
         hir::Constness::Const => true,
@@ -1424,7 +1425,7 @@ pub fn is_const_fn(cdata: Cmd, id: ast::NodeId) -> bool {
     }
 }
 
-pub fn is_impl(cdata: Cmd, id: ast::NodeId) -> bool {
+pub fn is_impl(cdata: Cmd, id: DefIndex) -> bool {
     let item_doc = cdata.lookup_item(id);
     match item_family(item_doc) {
         Impl => true,
@@ -1444,7 +1445,7 @@ fn doc_generics<'tcx>(base_doc: rbml::Doc,
     for p in reader::tagged_docs(doc, tag_type_param_def) {
         let bd =
             TyDecoder::with_doc(tcx, cdata.cnum, p,
-                                &mut |_, did| translate_def_id(cdata, did))
+                                &mut |did| translate_def_id(cdata, did))
             .parse_type_param_def();
         types.push(bd.space, bd);
     }
@@ -1466,7 +1467,7 @@ fn doc_generics<'tcx>(base_doc: rbml::Doc,
 
         let bounds = reader::tagged_docs(rp_doc, tag_items_data_region).map(|p| {
             TyDecoder::with_doc(tcx, cdata.cnum, p,
-                                &mut |_, did| translate_def_id(cdata, did))
+                                &mut |did| translate_def_id(cdata, did))
             .parse_region()
         }).collect();
 
@@ -1480,6 +1481,19 @@ fn doc_generics<'tcx>(base_doc: rbml::Doc,
     ty::Generics { types: types, regions: regions }
 }
 
+fn doc_predicate<'tcx>(cdata: Cmd,
+                       doc: rbml::Doc,
+                       tcx: &ty::ctxt<'tcx>)
+                       -> ty::Predicate<'tcx>
+{
+    let predicate_pos = cdata.xref_index.lookup(
+        cdata.data(), reader::doc_as_u32(doc)).unwrap() as usize;
+    TyDecoder::new(
+        cdata.data(), cdata.cnum, predicate_pos, tcx,
+        &mut |did| translate_def_id(cdata, did)
+    ).parse_predicate()
+}
+
 fn doc_predicates<'tcx>(base_doc: rbml::Doc,
                         tcx: &ty::ctxt<'tcx>,
                         cdata: Cmd,
@@ -1489,30 +1503,30 @@ fn doc_predicates<'tcx>(base_doc: rbml::Doc,
     let doc = reader::get_doc(base_doc, tag);
 
     let mut predicates = subst::VecPerParamSpace::empty();
-    for predicate_doc in reader::tagged_docs(doc, tag_predicate) {
-        let space_doc = reader::get_doc(predicate_doc, tag_predicate_space);
-        let space = subst::ParamSpace::from_uint(reader::doc_as_u8(space_doc) as usize);
-
-        let data_doc = reader::get_doc(predicate_doc, tag_predicate_data);
-        let data =
-            TyDecoder::with_doc(tcx, cdata.cnum, data_doc,
-                                &mut |_, did| translate_def_id(cdata, did))
-            .parse_predicate();
-
-        predicates.push(space, data);
+    for predicate_doc in reader::tagged_docs(doc, tag_type_predicate) {
+        predicates.push(subst::TypeSpace,
+                        doc_predicate(cdata, predicate_doc, tcx));
+    }
+    for predicate_doc in reader::tagged_docs(doc, tag_self_predicate) {
+        predicates.push(subst::SelfSpace,
+                        doc_predicate(cdata, predicate_doc, tcx));
+    }
+    for predicate_doc in reader::tagged_docs(doc, tag_fn_predicate) {
+        predicates.push(subst::FnSpace,
+                        doc_predicate(cdata, predicate_doc, tcx));
     }
 
     ty::GenericPredicates { predicates: predicates }
 }
 
-pub fn is_defaulted_trait(cdata: Cmd, trait_id: ast::NodeId) -> bool {
+pub fn is_defaulted_trait(cdata: Cmd, trait_id: DefIndex) -> bool {
     let trait_doc = cdata.lookup_item(trait_id);
     assert!(item_family(trait_doc) == Family::Trait);
     let defaulted_doc = reader::get_doc(trait_doc, tag_defaulted_trait);
     reader::doc_as_u8(defaulted_doc) != 0
 }
 
-pub fn is_default_impl(cdata: Cmd, impl_id: ast::NodeId) -> bool {
+pub fn is_default_impl(cdata: Cmd, impl_id: DefIndex) -> bool {
     let impl_doc = cdata.lookup_item(impl_id);
     item_family(impl_doc) == Family::DefaultImpl
 }
@@ -1527,7 +1541,7 @@ pub fn get_imported_filemaps(metadata: &[u8]) -> Vec<codemap::FileMap> {
     }).collect()
 }
 
-pub fn is_extern_fn(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt) -> bool {
+pub fn is_extern_fn(cdata: Cmd, id: DefIndex, tcx: &ty::ctxt) -> bool {
     let item_doc = match cdata.get_item(id) {
         Some(doc) => doc,
         None => return false,
@@ -1542,3 +1556,41 @@ pub fn is_extern_fn(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt) -> bool {
         false
     }
 }
+
+pub fn closure_kind(cdata: Cmd, closure_id: DefIndex) -> ty::ClosureKind {
+    let closure_doc = cdata.lookup_item(closure_id);
+    let closure_kind_doc = reader::get_doc(closure_doc, tag_items_closure_kind);
+    let mut decoder = reader::Decoder::new(closure_kind_doc);
+    ty::ClosureKind::decode(&mut decoder).unwrap()
+}
+
+pub fn closure_ty<'tcx>(cdata: Cmd, closure_id: DefIndex, tcx: &ty::ctxt<'tcx>)
+                        -> ty::ClosureTy<'tcx> {
+    let closure_doc = cdata.lookup_item(closure_id);
+    let closure_ty_doc = reader::get_doc(closure_doc, tag_items_closure_ty);
+    TyDecoder::with_doc(tcx, cdata.cnum, closure_ty_doc, &mut |did| translate_def_id(cdata, did))
+        .parse_closure_ty()
+}
+
+fn def_key(item_doc: rbml::Doc) -> hir_map::DefKey {
+    match reader::maybe_get_doc(item_doc, tag_def_key) {
+        Some(def_key_doc) => {
+            let mut decoder = reader::Decoder::new(def_key_doc);
+            hir_map::DefKey::decode(&mut decoder).unwrap()
+        }
+        None => {
+            panic!("failed to find block with tag {:?} for item with family {:?}",
+                   tag_def_key,
+                   item_family(item_doc))
+        }
+    }
+}
+
+pub fn def_path(cdata: Cmd, id: DefIndex) -> hir_map::DefPath {
+    debug!("def_path(id={:?})", id);
+    hir_map::definitions::make_def_path(id, |parent| {
+        debug!("def_path: parent={:?}", parent);
+        let parent_doc = cdata.lookup_item(parent);
+        def_key(parent_doc)
+    })
+}
index ff24541692eccfd6ceaa80fdf368d628c6f30eac..8e2c2e6a0bfbd2d0ce8fc09f787ee967edf3bd91 100644 (file)
@@ -17,14 +17,16 @@ use back::svh::Svh;
 use session::config;
 use metadata::common::*;
 use metadata::cstore;
+use metadata::cstore::LOCAL_CRATE;
 use metadata::decoder;
 use metadata::tyencode;
-use metadata::index::{self, IndexEntry};
+use metadata::index::{self, IndexData};
 use metadata::inline::InlinedItemRef;
 use middle::def;
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::{CRATE_DEF_INDEX, DefId};
 use middle::dependency_format::Linkage;
 use middle::stability;
+use middle::subst;
 use middle::ty::{self, Ty};
 use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
 
@@ -33,18 +35,19 @@ use std::cell::RefCell;
 use std::io::prelude::*;
 use std::io::{Cursor, SeekFrom};
 use std::rc::Rc;
+use std::u32;
 use syntax::abi;
-use syntax::ast::{NodeId, Name, CRATE_NODE_ID, CrateNum};
+use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum};
+use syntax::attr;
+use syntax::attr::AttrMetaMethods;
 use syntax::diagnostic::SpanHandler;
 use syntax::parse::token::special_idents;
 use syntax;
 use rbml::writer::Encoder;
 
-use rustc_front::hir as ast;
+use rustc_front::hir;
 use rustc_front::visit::Visitor;
 use rustc_front::visit;
-use rustc_front::attr;
-use rustc_front::attr::AttrMetaMethods;
 use front::map::{LinkedPath, PathElem, PathElems};
 use front::map as ast_map;
 
@@ -74,18 +77,61 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
     pub reachable: &'a NodeSet,
 }
 
-fn encode_name(rbml_w: &mut Encoder, name: Name) {
-    rbml_w.wr_tagged_str(tag_paths_data_name, &name.as_str());
+impl<'a, 'tcx> EncodeContext<'a,'tcx> {
+    fn local_id(&self, def_id: DefId) -> NodeId {
+        self.tcx.map.as_local_node_id(def_id).unwrap()
+    }
+}
+
+/// "interned" entries referenced by id
+#[derive(PartialEq, Eq, Hash)]
+pub enum XRef<'tcx> { Predicate(ty::Predicate<'tcx>) }
+
+struct CrateIndex<'tcx> {
+    items: IndexData,
+    xrefs: FnvHashMap<XRef<'tcx>, u32>, // sequentially-assigned
 }
 
-fn encode_impl_type_basename(rbml_w: &mut Encoder, name: Name) {
-    rbml_w.wr_tagged_str(tag_item_impl_type_basename, &name.as_str());
+impl<'tcx> CrateIndex<'tcx> {
+    fn record(&mut self, id: DefId, rbml_w: &mut Encoder) {
+        let position = rbml_w.mark_stable_position();
+        self.items.record(id, position);
+    }
+
+    fn add_xref(&mut self, xref: XRef<'tcx>) -> u32 {
+        let old_len = self.xrefs.len() as u32;
+        *self.xrefs.entry(xref).or_insert(old_len)
+    }
+}
+
+fn encode_name(rbml_w: &mut Encoder, name: Name) {
+    rbml_w.wr_tagged_str(tag_paths_data_name, &name.as_str());
 }
 
 fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
     rbml_w.wr_tagged_u64(tag_def_id, def_to_u64(id));
 }
 
+/// For every DefId that we create a metadata item for, we include a
+/// serialized copy of its DefKey, which allows us to recreate a path.
+fn encode_def_id_and_key(ecx: &EncodeContext,
+                         rbml_w: &mut Encoder,
+                         def_id: DefId)
+{
+    encode_def_id(rbml_w, def_id);
+    encode_def_key(ecx, rbml_w, def_id);
+}
+
+fn encode_def_key(ecx: &EncodeContext,
+                  rbml_w: &mut Encoder,
+                  def_id: DefId)
+{
+    rbml_w.start_tag(tag_def_key);
+    let def_key = ecx.tcx.map.def_key(def_id);
+    def_key.encode(rbml_w);
+    rbml_w.end_tag();
+}
+
 fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder,
                               ecx: &EncodeContext<'a, 'tcx>,
                               trait_ref: ty::TraitRef<'tcx>,
@@ -108,17 +154,18 @@ fn encode_family(rbml_w: &mut Encoder, c: char) {
 }
 
 pub fn def_to_u64(did: DefId) -> u64 {
-    (did.krate as u64) << 32 | (did.node as u64)
+    assert!(did.index.as_u32() < u32::MAX);
+    (did.krate as u64) << 32 | (did.index.as_usize() as u64)
 }
 
 pub fn def_to_string(did: DefId) -> String {
-    format!("{}:{}", did.krate, did.node)
+    format!("{}:{}", did.krate, did.index.as_usize())
 }
 
 fn encode_item_variances(rbml_w: &mut Encoder,
                          ecx: &EncodeContext,
                          id: NodeId) {
-    let v = ecx.tcx.item_variances(DefId::local(id));
+    let v = ecx.tcx.item_variances(ecx.tcx.map.local_def_id(id));
     rbml_w.start_tag(tag_item_variances);
     v.encode(rbml_w);
     rbml_w.end_tag();
@@ -126,18 +173,22 @@ fn encode_item_variances(rbml_w: &mut Encoder,
 
 fn encode_bounds_and_type_for_item<'a, 'tcx>(rbml_w: &mut Encoder,
                                              ecx: &EncodeContext<'a, 'tcx>,
+                                             index: &mut CrateIndex<'tcx>,
                                              id: NodeId) {
     encode_bounds_and_type(rbml_w,
                            ecx,
-                           &ecx.tcx.lookup_item_type(DefId::local(id)),
-                           &ecx.tcx.lookup_predicates(DefId::local(id)));
+                           index,
+                           &ecx.tcx.lookup_item_type(ecx.tcx.map.local_def_id(id)),
+                           &ecx.tcx.lookup_predicates(ecx.tcx.map.local_def_id(id)));
 }
 
 fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder,
                                     ecx: &EncodeContext<'a, 'tcx>,
+                                    index: &mut CrateIndex<'tcx>,
                                     scheme: &ty::TypeScheme<'tcx>,
                                     predicates: &ty::GenericPredicates<'tcx>) {
-    encode_generics(rbml_w, ecx, &scheme.generics, &predicates, tag_item_generics);
+    encode_generics(rbml_w, ecx, index,
+                    &scheme.generics, &predicates, tag_item_generics);
     encode_type(ecx, rbml_w, scheme.ty);
 }
 
@@ -211,22 +262,6 @@ fn encode_region(ecx: &EncodeContext,
     rbml_w.end_tag();
 }
 
-fn encode_method_fty<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
-                               rbml_w: &mut Encoder,
-                               typ: &ty::BareFnTy<'tcx>) {
-    rbml_w.start_tag(tag_item_method_fty);
-
-    let ty_str_ctxt = &tyencode::ctxt {
-        diag: ecx.diag,
-        ds: def_to_string,
-        tcx: ecx.tcx,
-        abbrevs: &ecx.type_abbrevs
-    };
-    tyencode::enc_bare_fn_ty(rbml_w, ty_str_ctxt, typ);
-
-    rbml_w.end_tag();
-}
-
 fn encode_symbol(ecx: &EncodeContext,
                  rbml_w: &mut Encoder,
                  id: NodeId) {
@@ -253,8 +288,7 @@ fn encode_parent_item(rbml_w: &mut Encoder, id: DefId) {
 }
 
 fn encode_struct_fields(rbml_w: &mut Encoder,
-                        variant: ty::VariantDef,
-                        origin: DefId) {
+                        variant: ty::VariantDef) {
     for f in &variant.fields {
         if f.name == special_idents::unnamed_field.name {
             rbml_w.start_tag(tag_item_unnamed_field);
@@ -264,25 +298,24 @@ fn encode_struct_fields(rbml_w: &mut Encoder,
         }
         encode_struct_field_family(rbml_w, f.vis);
         encode_def_id(rbml_w, f.did);
-        rbml_w.wr_tagged_u64(tag_item_field_origin, def_to_u64(origin));
         rbml_w.end_tag();
     }
 }
 
-fn encode_enum_variant_info(ecx: &EncodeContext,
-                            rbml_w: &mut Encoder,
-                            id: NodeId,
-                            vis: ast::Visibility,
-                            index: &mut Vec<IndexEntry>) {
+fn encode_enum_variant_info<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
+                                      rbml_w: &mut Encoder,
+                                      id: NodeId,
+                                      vis: hir::Visibility,
+                                      index: &mut CrateIndex<'tcx>) {
     debug!("encode_enum_variant_info(id={})", id);
 
     let mut disr_val = 0;
-    let def = ecx.tcx.lookup_adt_def(DefId::local(id));
+    let def = ecx.tcx.lookup_adt_def(ecx.tcx.map.local_def_id(id));
     for variant in &def.variants {
         let vid = variant.did;
-        assert!(vid.is_local());
+        let variant_node_id = ecx.local_id(vid);
 
-        if let ty::VariantKind::Dict = variant.kind() {
+        if let ty::VariantKind::Struct = variant.kind() {
             // tuple-like enum variant fields aren't really items so
             // don't try to encode them.
             for field in &variant.fields {
@@ -290,18 +323,15 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
             }
         }
 
-        index.push(IndexEntry {
-            node: vid.node,
-            pos: rbml_w.mark_stable_position(),
-        });
+        index.record(vid, rbml_w);
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, vid);
+        encode_def_id_and_key(ecx, rbml_w, vid);
         encode_family(rbml_w, match variant.kind() {
             ty::VariantKind::Unit | ty::VariantKind::Tuple => 'v',
-            ty::VariantKind::Dict => 'V'
+            ty::VariantKind::Struct => 'V'
         });
         encode_name(rbml_w, variant.name);
-        encode_parent_item(rbml_w, DefId::local(id));
+        encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(id));
         encode_visibility(rbml_w, vis);
 
         let attrs = ecx.tcx.get_attrs(vid);
@@ -311,16 +341,16 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
         let stab = stability::lookup(ecx.tcx, vid);
         encode_stability(rbml_w, stab);
 
-        encode_struct_fields(rbml_w, variant, vid);
+        encode_struct_fields(rbml_w, variant);
 
         let specified_disr_val = variant.disr_val;
         if specified_disr_val != disr_val {
             encode_disr_val(ecx, rbml_w, specified_disr_val);
             disr_val = specified_disr_val;
         }
-        encode_bounds_and_type_for_item(rbml_w, ecx, vid.node);
+        encode_bounds_and_type_for_item(rbml_w, ecx, index, variant_node_id);
 
-        ecx.tcx.map.with_path(vid.node, |path| encode_path(rbml_w, path));
+        ecx.tcx.map.with_path(variant_node_id, |path| encode_path(rbml_w, path));
         rbml_w.end_tag();
         disr_val = disr_val.wrapping_add(1);
     }
@@ -340,124 +370,19 @@ fn encode_path<PI: Iterator<Item=PathElem>>(rbml_w: &mut Encoder, path: PI) {
     rbml_w.end_tag();
 }
 
-fn encode_reexported_static_method(rbml_w: &mut Encoder,
-                                   exp: &def::Export,
-                                   method_def_id: DefId,
-                                   method_name: Name) {
-    debug!("(encode reexported static method) {}::{}",
-            exp.name, method_name);
-    rbml_w.start_tag(tag_items_data_item_reexport);
-    rbml_w.wr_tagged_u64(tag_items_data_item_reexport_def_id,
-                         def_to_u64(method_def_id));
-    rbml_w.wr_tagged_str(tag_items_data_item_reexport_name,
-                         &format!("{}::{}", exp.name,
-                                            method_name));
-    rbml_w.end_tag();
-}
-
-fn encode_reexported_static_base_methods(ecx: &EncodeContext,
-                                         rbml_w: &mut Encoder,
-                                         exp: &def::Export)
-                                         -> bool {
-    let impl_items = ecx.tcx.impl_items.borrow();
-    match ecx.tcx.inherent_impls.borrow().get(&exp.def_id) {
-        Some(implementations) => {
-            for base_impl_did in implementations.iter() {
-                for &method_did in impl_items.get(base_impl_did).unwrap() {
-                    let impl_item = ecx.tcx.impl_or_trait_item(method_did.def_id());
-                    if let ty::MethodTraitItem(ref m) = impl_item {
-                        encode_reexported_static_method(rbml_w,
-                                                        exp,
-                                                        m.def_id,
-                                                        m.name);
-                    }
-                }
-            }
-
-            true
-        }
-        None => { false }
-    }
-}
-
-fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
-                                          rbml_w: &mut Encoder,
-                                          exp: &def::Export)
-                                          -> bool {
-    match ecx.tcx.trait_items_cache.borrow().get(&exp.def_id) {
-        Some(trait_items) => {
-            for trait_item in trait_items.iter() {
-                if let ty::MethodTraitItem(ref m) = *trait_item {
-                    encode_reexported_static_method(rbml_w,
-                                                    exp,
-                                                    m.def_id,
-                                                    m.name);
-                }
-            }
-            true
-        }
-        None => { false }
-    }
-}
-
-fn encode_reexported_static_methods(ecx: &EncodeContext,
-                                    rbml_w: &mut Encoder,
-                                    mod_path: PathElems,
-                                    exp: &def::Export) {
-    if let Some(ast_map::NodeItem(item)) = ecx.tcx.map.find(exp.def_id.node) {
-        let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
-            let (mut a, mut b) = (path, mod_path.clone());
-            loop {
-                match (a.next(), b.next()) {
-                    (None, None) => return true,
-                    (None, _) | (_, None) => return false,
-                    (Some(x), Some(y)) => if x != y { return false },
-                }
-            }
-        });
-
-        //
-        // We don't need to reexport static methods on items
-        // declared in the same module as our `pub use ...` since
-        // that's done when we encode the item itself.
-        //
-        // The only exception is when the reexport *changes* the
-        // name e.g. `pub use Foo = self::Bar` -- we have
-        // encoded metadata for static methods relative to Bar,
-        // but not yet for Foo.
-        //
-        if path_differs || item.ident.name != exp.name {
-            if !encode_reexported_static_base_methods(ecx, rbml_w, exp) {
-                if encode_reexported_static_trait_methods(ecx, rbml_w, exp) {
-                    debug!("(encode reexported static methods) {} [trait]",
-                           item.ident.name);
-                }
-            }
-            else {
-                debug!("(encode reexported static methods) {} [base]",
-                       item.ident.name);
-            }
-        }
-    }
-}
-
 /// Iterates through "auxiliary node IDs", which are node IDs that describe
 /// top-level items that are sub-items of the given item. Specifically:
 ///
 /// * For newtype structs, iterates through the node ID of the constructor.
-fn each_auxiliary_node_id<F>(item: &ast::Item, callback: F) -> bool where
+fn each_auxiliary_node_id<F>(item: &hir::Item, callback: F) -> bool where
     F: FnOnce(NodeId) -> bool,
 {
     let mut continue_ = true;
     match item.node {
-        ast::ItemStruct(ref struct_def, _) => {
+        hir::ItemStruct(ref struct_def, _) => {
             // If this is a newtype struct, return the constructor.
-            match struct_def.ctor_id {
-                Some(ctor_id) if !struct_def.fields.is_empty() &&
-                        struct_def.fields[0].node.kind.is_unnamed() => {
-                    continue_ = callback(ctor_id);
-                }
-                _ => {}
+            if struct_def.is_tuple() {
+                continue_ = callback(struct_def.id());
             }
         }
         _ => {}
@@ -468,18 +393,16 @@ fn each_auxiliary_node_id<F>(item: &ast::Item, callback: F) -> bool where
 
 fn encode_reexports(ecx: &EncodeContext,
                     rbml_w: &mut Encoder,
-                    id: NodeId,
-                    path: PathElems) {
+                    id: NodeId) {
     debug!("(encoding info for module) encoding reexports for {}", id);
     match ecx.reexports.get(&id) {
         Some(exports) => {
             debug!("(encoding info for module) found reexports for {}", id);
             for exp in exports {
-                debug!("(encoding info for module) reexport '{}' ({}/{}) for \
+                debug!("(encoding info for module) reexport '{}' ({:?}) for \
                         {}",
                        exp.name,
-                       exp.def_id.krate,
-                       exp.def_id.node,
+                       exp.def_id,
                        id);
                 rbml_w.start_tag(tag_items_data_item_reexport);
                 rbml_w.wr_tagged_u64(tag_items_data_item_reexport_def_id,
@@ -487,7 +410,6 @@ fn encode_reexports(ecx: &EncodeContext,
                 rbml_w.wr_tagged_str(tag_items_data_item_reexport_name,
                                      &exp.name.as_str());
                 rbml_w.end_tag();
-                encode_reexported_static_methods(ecx, rbml_w, path.clone(), exp);
             }
         },
         None => debug!("(encoding info for module) found no reexports for {}", id),
@@ -496,14 +418,14 @@ fn encode_reexports(ecx: &EncodeContext,
 
 fn encode_info_for_mod(ecx: &EncodeContext,
                        rbml_w: &mut Encoder,
-                       md: &ast::Mod,
+                       md: &hir::Mod,
                        attrs: &[ast::Attribute],
                        id: NodeId,
                        path: PathElems,
                        name: Name,
-                       vis: ast::Visibility) {
+                       vis: hir::Visibility) {
     rbml_w.start_tag(tag_items_data_item);
-    encode_def_id(rbml_w, DefId::local(id));
+    encode_def_id_and_key(ecx, rbml_w, ecx.tcx.map.local_def_id(id));
     encode_family(rbml_w, 'm');
     encode_name(rbml_w, name);
     debug!("(encoding info for module) encoding info for module ID {}", id);
@@ -511,34 +433,25 @@ fn encode_info_for_mod(ecx: &EncodeContext,
     // Encode info about all the module children.
     for item in &md.items {
         rbml_w.wr_tagged_u64(tag_mod_child,
-                             def_to_u64(DefId::local(item.id)));
+                             def_to_u64(ecx.tcx.map.local_def_id(item.id)));
 
         each_auxiliary_node_id(&**item, |auxiliary_node_id| {
             rbml_w.wr_tagged_u64(tag_mod_child,
-                                 def_to_u64(DefId::local(auxiliary_node_id)));
+                                 def_to_u64(ecx.tcx.map.local_def_id(auxiliary_node_id)));
             true
         });
-
-        if let ast::ItemImpl(..) = item.node {
-            let (ident, did) = (item.ident, item.id);
-            debug!("(encoding info for module) ... encoding impl {} ({}/{})",
-                   ident,
-                   did, ecx.tcx.map.node_to_string(did));
-
-            rbml_w.wr_tagged_u64(tag_mod_impl, def_to_u64(DefId::local(did)));
-        }
     }
 
     encode_path(rbml_w, path.clone());
     encode_visibility(rbml_w, vis);
 
-    let stab = stability::lookup(ecx.tcx, DefId::local(id));
+    let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(id));
     encode_stability(rbml_w, stab);
 
     // Encode the reexports of this module, if this module is public.
-    if vis == ast::Public {
+    if vis == hir::Public {
         debug!("(encoding info for module) encoding reexports for {}", id);
-        encode_reexports(ecx, rbml_w, id, path);
+        encode_reexports(ecx, rbml_w, id);
     }
     encode_attributes(rbml_w, attrs);
 
@@ -546,26 +459,26 @@ fn encode_info_for_mod(ecx: &EncodeContext,
 }
 
 fn encode_struct_field_family(rbml_w: &mut Encoder,
-                              visibility: ast::Visibility) {
+                              visibility: hir::Visibility) {
     encode_family(rbml_w, match visibility {
-        ast::Public => 'g',
-        ast::Inherited => 'N'
+        hir::Public => 'g',
+        hir::Inherited => 'N'
     });
 }
 
-fn encode_visibility(rbml_w: &mut Encoder, visibility: ast::Visibility) {
+fn encode_visibility(rbml_w: &mut Encoder, visibility: hir::Visibility) {
     let ch = match visibility {
-        ast::Public => 'y',
-        ast::Inherited => 'i',
+        hir::Public => 'y',
+        hir::Inherited => 'i',
     };
     rbml_w.wr_tagged_u8(tag_items_data_item_visibility, ch as u8);
 }
 
-fn encode_constness(rbml_w: &mut Encoder, constness: ast::Constness) {
+fn encode_constness(rbml_w: &mut Encoder, constness: hir::Constness) {
     rbml_w.start_tag(tag_items_data_item_constness);
     let ch = match constness {
-        ast::Constness::Const => 'c',
-        ast::Constness::NotConst => 'n',
+        hir::Constness::Const => 'c',
+        hir::Constness::NotConst => 'n',
     };
     rbml_w.wr_str(&ch.to_string());
     rbml_w.end_tag();
@@ -593,10 +506,10 @@ fn encode_explicit_self(rbml_w: &mut Encoder,
         }
     }
 
-    fn encode_mutability(m: ast::Mutability) -> u8 {
+    fn encode_mutability(m: hir::Mutability) -> u8 {
         match m {
-            ast::MutImmutable => 'i' as u8,
-            ast::MutMutable => 'm' as u8,
+            hir::MutImmutable => 'i' as u8,
+            hir::MutMutable => 'm' as u8,
         }
     }
 }
@@ -605,35 +518,20 @@ fn encode_item_sort(rbml_w: &mut Encoder, sort: char) {
     rbml_w.wr_tagged_u8(tag_item_trait_item_sort, sort as u8);
 }
 
-fn encode_parent_sort(rbml_w: &mut Encoder, sort: char) {
-    rbml_w.wr_tagged_u8(tag_item_trait_parent_sort, sort as u8);
-}
-
-fn encode_provided_source(rbml_w: &mut Encoder,
-                          source_opt: Option<DefId>) {
-    if let Some(source) = source_opt {
-        rbml_w.wr_tagged_u64(tag_item_method_provided_source, def_to_u64(source));
-    }
-}
-
 fn encode_field<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
                           rbml_w: &mut Encoder,
                           field: ty::FieldDef<'tcx>,
-                          global_index: &mut Vec<IndexEntry>) {
+                          index: &mut CrateIndex<'tcx>) {
     let nm = field.name;
-    let id = field.did.node;
+    let id = ecx.local_id(field.did);
 
-    let pos = rbml_w.mark_stable_position();
-    global_index.push(IndexEntry {
-        node: id,
-        pos: pos,
-    });
+    index.record(field.did, rbml_w);
     rbml_w.start_tag(tag_items_data_item);
     debug!("encode_field: encoding {} {}", nm, id);
     encode_struct_field_family(rbml_w, field.vis);
     encode_name(rbml_w, nm);
-    encode_bounds_and_type_for_item(rbml_w, ecx, id);
-    encode_def_id(rbml_w, DefId::local(id));
+    encode_bounds_and_type_for_item(rbml_w, ecx, index, id);
+    encode_def_id_and_key(ecx, rbml_w, field.did);
 
     let stab = stability::lookup(ecx.tcx, field.did);
     encode_stability(rbml_w, stab);
@@ -641,30 +539,28 @@ fn encode_field<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
     rbml_w.end_tag();
 }
 
-fn encode_info_for_struct_ctor(ecx: &EncodeContext,
-                               rbml_w: &mut Encoder,
-                               name: Name,
-                               ctor_id: NodeId,
-                               index: &mut Vec<IndexEntry>,
-                               struct_id: NodeId) {
-    index.push(IndexEntry {
-        node: ctor_id,
-        pos: rbml_w.mark_stable_position(),
-    });
+fn encode_info_for_struct_ctor<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
+                                         rbml_w: &mut Encoder,
+                                         name: Name,
+                                         ctor_id: NodeId,
+                                         index: &mut CrateIndex<'tcx>,
+                                         struct_id: NodeId) {
+    let ctor_def_id = ecx.tcx.map.local_def_id(ctor_id);
 
+    index.record(ctor_def_id, rbml_w);
     rbml_w.start_tag(tag_items_data_item);
-    encode_def_id(rbml_w, DefId::local(ctor_id));
+    encode_def_id_and_key(ecx, rbml_w, ctor_def_id);
     encode_family(rbml_w, 'o');
-    encode_bounds_and_type_for_item(rbml_w, ecx, ctor_id);
+    encode_bounds_and_type_for_item(rbml_w, ecx, index, ctor_id);
     encode_name(rbml_w, name);
     ecx.tcx.map.with_path(ctor_id, |path| encode_path(rbml_w, path));
-    encode_parent_item(rbml_w, DefId::local(struct_id));
+    encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(struct_id));
 
     if ecx.item_symbols.borrow().contains_key(&ctor_id) {
         encode_symbol(ecx, rbml_w, ctor_id);
     }
 
-    let stab = stability::lookup(ecx.tcx, DefId::local(ctor_id));
+    let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(ctor_id));
     encode_stability(rbml_w, stab);
 
     // indicate that this is a tuple struct ctor, because downstream users will normally want
@@ -677,6 +573,7 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext,
 
 fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
                              ecx: &EncodeContext<'a, 'tcx>,
+                             index: &mut CrateIndex<'tcx>,
                              generics: &ty::Generics<'tcx>,
                              predicates: &ty::GenericPredicates<'tcx>,
                              tag: usize)
@@ -721,53 +618,48 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
         rbml_w.end_tag();
     }
 
-    encode_predicates_in_current_doc(rbml_w, ecx, predicates);
+    encode_predicates_in_current_doc(rbml_w, ecx, index, predicates);
 
     rbml_w.end_tag();
 }
 
 fn encode_predicates_in_current_doc<'a,'tcx>(rbml_w: &mut Encoder,
-                                             ecx: &EncodeContext<'a,'tcx>,
+                                             _ecx: &EncodeContext<'a,'tcx>,
+                                             index: &mut CrateIndex<'tcx>,
                                              predicates: &ty::GenericPredicates<'tcx>)
 {
-    let ty_str_ctxt = &tyencode::ctxt {
-        diag: ecx.diag,
-        ds: def_to_string,
-        tcx: ecx.tcx,
-        abbrevs: &ecx.type_abbrevs
-    };
-
     for (space, _, predicate) in predicates.predicates.iter_enumerated() {
-        rbml_w.start_tag(tag_predicate);
-
-        rbml_w.wr_tagged_u8(tag_predicate_space, space as u8);
-
-        rbml_w.start_tag(tag_predicate_data);
-        tyencode::enc_predicate(rbml_w, ty_str_ctxt, predicate);
-        rbml_w.end_tag();
+        let tag = match space {
+            subst::TypeSpace => tag_type_predicate,
+            subst::SelfSpace => tag_self_predicate,
+            subst::FnSpace => tag_fn_predicate
+        };
 
-        rbml_w.end_tag();
+        rbml_w.wr_tagged_u32(tag,
+            index.add_xref(XRef::Predicate(predicate.clone())));
     }
 }
 
 fn encode_predicates<'a,'tcx>(rbml_w: &mut Encoder,
                               ecx: &EncodeContext<'a,'tcx>,
+                              index: &mut CrateIndex<'tcx>,
                               predicates: &ty::GenericPredicates<'tcx>,
                               tag: usize)
 {
     rbml_w.start_tag(tag);
-    encode_predicates_in_current_doc(rbml_w, ecx, predicates);
+    encode_predicates_in_current_doc(rbml_w, ecx, index, predicates);
     rbml_w.end_tag();
 }
 
 fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
                                      rbml_w: &mut Encoder,
+                                     index: &mut CrateIndex<'tcx>,
                                      method_ty: &ty::Method<'tcx>) {
-    encode_def_id(rbml_w, method_ty.def_id);
+    encode_def_id_and_key(ecx, rbml_w, method_ty.def_id);
     encode_name(rbml_w, method_ty.name);
-    encode_generics(rbml_w, ecx, &method_ty.generics, &method_ty.predicates,
+    encode_generics(rbml_w, ecx, index,
+                    &method_ty.generics, &method_ty.predicates,
                     tag_method_ty_generics);
-    encode_method_fty(ecx, rbml_w, &method_ty.fty);
     encode_visibility(rbml_w, method_ty.vis);
     encode_explicit_self(rbml_w, &method_ty.explicit_self);
     match method_ty.explicit_self {
@@ -776,31 +668,32 @@ fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
         }
         _ => encode_family(rbml_w, METHOD_FAMILY)
     }
-    encode_provided_source(rbml_w, method_ty.provided_source);
 }
 
-fn encode_info_for_associated_const(ecx: &EncodeContext,
-                                    rbml_w: &mut Encoder,
-                                    associated_const: &ty::AssociatedConst,
-                                    impl_path: PathElems,
-                                    parent_id: NodeId,
-                                    impl_item_opt: Option<&ast::ImplItem>) {
+fn encode_info_for_associated_const<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
+                                              rbml_w: &mut Encoder,
+                                              index: &mut CrateIndex<'tcx>,
+                                              associated_const: &ty::AssociatedConst,
+                                              impl_path: PathElems,
+                                              parent_id: NodeId,
+                                              impl_item_opt: Option<&hir::ImplItem>) {
     debug!("encode_info_for_associated_const({:?},{:?})",
            associated_const.def_id,
            associated_const.name);
 
+    index.record(associated_const.def_id, rbml_w);
     rbml_w.start_tag(tag_items_data_item);
 
-    encode_def_id(rbml_w, associated_const.def_id);
+    encode_def_id_and_key(ecx, rbml_w, associated_const.def_id);
     encode_name(rbml_w, associated_const.name);
     encode_visibility(rbml_w, associated_const.vis);
     encode_family(rbml_w, 'C');
-    encode_provided_source(rbml_w, associated_const.default);
 
-    encode_parent_item(rbml_w, DefId::local(parent_id));
+    encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
     encode_item_sort(rbml_w, 'C');
 
-    encode_bounds_and_type_for_item(rbml_w, ecx, associated_const.def_id.local_id());
+    encode_bounds_and_type_for_item(rbml_w, ecx, index,
+                                    ecx.local_id(associated_const.def_id));
 
     let stab = stability::lookup(ecx.tcx, associated_const.def_id);
     encode_stability(rbml_w, stab);
@@ -810,7 +703,10 @@ fn encode_info_for_associated_const(ecx: &EncodeContext,
 
     if let Some(ii) = impl_item_opt {
         encode_attributes(rbml_w, &ii.attrs);
-        encode_inlined_item(ecx, rbml_w, InlinedItemRef::ImplItem(DefId::local(parent_id), ii));
+        encode_inlined_item(ecx,
+                            rbml_w,
+                            InlinedItemRef::ImplItem(ecx.tcx.map.local_def_id(parent_id),
+                                                     ii));
     }
 
     rbml_w.end_tag();
@@ -818,42 +714,47 @@ fn encode_info_for_associated_const(ecx: &EncodeContext,
 
 fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
                                     rbml_w: &mut Encoder,
+                                    index: &mut CrateIndex<'tcx>,
                                     m: &ty::Method<'tcx>,
                                     impl_path: PathElems,
                                     is_default_impl: bool,
                                     parent_id: NodeId,
-                                    impl_item_opt: Option<&ast::ImplItem>) {
+                                    impl_item_opt: Option<&hir::ImplItem>) {
 
     debug!("encode_info_for_method: {:?} {:?}", m.def_id,
            m.name);
+    index.record(m.def_id, rbml_w);
     rbml_w.start_tag(tag_items_data_item);
 
-    encode_method_ty_fields(ecx, rbml_w, m);
-    encode_parent_item(rbml_w, DefId::local(parent_id));
+    encode_method_ty_fields(ecx, rbml_w, index, m);
+    encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
     encode_item_sort(rbml_w, 'r');
 
     let stab = stability::lookup(ecx.tcx, m.def_id);
     encode_stability(rbml_w, stab);
 
-    // The type for methods gets encoded twice, which is unfortunate.
-    encode_bounds_and_type_for_item(rbml_w, ecx, m.def_id.local_id());
+    let m_node_id = ecx.local_id(m.def_id);
+    encode_bounds_and_type_for_item(rbml_w, ecx, index, m_node_id);
 
     let elem = ast_map::PathName(m.name);
     encode_path(rbml_w, impl_path.chain(Some(elem)));
     if let Some(impl_item) = impl_item_opt {
-        if let ast::MethodImplItem(ref sig, _) = impl_item.node {
+        if let hir::MethodImplItem(ref sig, _) = impl_item.node {
             encode_attributes(rbml_w, &impl_item.attrs);
             let scheme = ecx.tcx.lookup_item_type(m.def_id);
             let any_types = !scheme.generics.types.is_empty();
             let needs_inline = any_types || is_default_impl ||
                                attr::requests_inline(&impl_item.attrs);
-            if needs_inline || sig.constness == ast::Constness::Const {
-                encode_inlined_item(ecx, rbml_w, InlinedItemRef::ImplItem(DefId::local(parent_id),
-                                                               impl_item));
+            if needs_inline || sig.constness == hir::Constness::Const {
+                encode_inlined_item(ecx,
+                                    rbml_w,
+                                    InlinedItemRef::ImplItem(ecx.tcx.map.local_def_id(parent_id),
+                                                             impl_item));
             }
             encode_constness(rbml_w, sig.constness);
             if !any_types {
-                encode_symbol(ecx, rbml_w, m.def_id.node);
+                let m_id = ecx.local_id(m.def_id);
+                encode_symbol(ecx, rbml_w, m_id);
             }
             encode_method_argument_names(rbml_w, &sig.decl);
         }
@@ -864,21 +765,23 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
 
 fn encode_info_for_associated_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
                                              rbml_w: &mut Encoder,
+                                             index: &mut CrateIndex<'tcx>,
                                              associated_type: &ty::AssociatedType<'tcx>,
                                              impl_path: PathElems,
                                              parent_id: NodeId,
-                                             impl_item_opt: Option<&ast::ImplItem>) {
+                                             impl_item_opt: Option<&hir::ImplItem>) {
     debug!("encode_info_for_associated_type({:?},{:?})",
            associated_type.def_id,
            associated_type.name);
 
+    index.record(associated_type.def_id, rbml_w);
     rbml_w.start_tag(tag_items_data_item);
 
-    encode_def_id(rbml_w, associated_type.def_id);
+    encode_def_id_and_key(ecx, rbml_w, associated_type.def_id);
     encode_name(rbml_w, associated_type.name);
     encode_visibility(rbml_w, associated_type.vis);
     encode_family(rbml_w, 'y');
-    encode_parent_item(rbml_w, DefId::local(parent_id));
+    encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
     encode_item_sort(rbml_w, 't');
 
     let stab = stability::lookup(ecx.tcx, associated_type.def_id);
@@ -890,7 +793,7 @@ fn encode_info_for_associated_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
     if let Some(ii) = impl_item_opt {
         encode_attributes(rbml_w, &ii.attrs);
     } else {
-        encode_predicates(rbml_w, ecx,
+        encode_predicates(rbml_w, ecx, index,
                           &ecx.tcx.lookup_predicates(associated_type.def_id),
                           tag_item_generics);
     }
@@ -903,11 +806,11 @@ fn encode_info_for_associated_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
 }
 
 fn encode_method_argument_names(rbml_w: &mut Encoder,
-                                decl: &ast::FnDecl) {
+                                decl: &hir::FnDecl) {
     rbml_w.start_tag(tag_method_argument_names);
     for arg in &decl.inputs {
         let tag = tag_method_argument_name;
-        if let ast::PatIdent(_, ref path1, _) = arg.pat.node {
+        if let hir::PatIdent(_, ref path1, _) = arg.pat.node {
             let name = path1.node.name.as_str();
             rbml_w.wr_tagged_bytes(tag, name.as_bytes());
         } else {
@@ -958,20 +861,6 @@ fn encode_inherent_implementations(ecx: &EncodeContext,
     }
 }
 
-// Encodes the implementations of a trait defined in this crate.
-fn encode_extension_implementations(ecx: &EncodeContext,
-                                    rbml_w: &mut Encoder,
-                                    trait_def_id: DefId) {
-    assert!(trait_def_id.is_local());
-    let def = ecx.tcx.lookup_trait_def(trait_def_id);
-
-    def.for_each_impl(ecx.tcx, |impl_def_id| {
-        rbml_w.start_tag(tag_items_data_item_extension_impl);
-        encode_def_id(rbml_w, impl_def_id);
-        rbml_w.end_tag();
-    });
-}
-
 fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<&attr::Stability>) {
     stab_opt.map(|stab| {
         rbml_w.start_tag(tag_items_data_item_stability);
@@ -980,54 +869,74 @@ fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<&attr::Stability>) {
     });
 }
 
-fn encode_info_for_item(ecx: &EncodeContext,
-                        rbml_w: &mut Encoder,
-                        item: &ast::Item,
-                        index: &mut Vec<IndexEntry>,
-                        path: PathElems,
-                        vis: ast::Visibility) {
-    let tcx = ecx.tcx;
+fn encode_xrefs<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
+                          rbml_w: &mut Encoder,
+                          xrefs: FnvHashMap<XRef<'tcx>, u32>)
+{
+    let ty_str_ctxt = &tyencode::ctxt {
+        diag: ecx.diag,
+        ds: def_to_string,
+        tcx: ecx.tcx,
+        abbrevs: &ecx.type_abbrevs
+    };
 
-    fn add_to_index(item: &ast::Item, rbml_w: &mut Encoder,
-                    index: &mut Vec<IndexEntry>) {
-        index.push(IndexEntry {
-            node: item.id,
-            pos: rbml_w.mark_stable_position(),
-        });
+    let mut xref_positions = vec![0; xrefs.len()];
+    rbml_w.start_tag(tag_xref_data);
+    for (xref, id) in xrefs.into_iter() {
+        xref_positions[id as usize] = rbml_w.mark_stable_position() as u32;
+        match xref {
+            XRef::Predicate(p) => {
+                tyencode::enc_predicate(rbml_w, ty_str_ctxt, &p)
+            }
+        }
     }
+    rbml_w.end_tag();
+
+    rbml_w.start_tag(tag_xref_index);
+    index::write_dense_index(xref_positions, rbml_w.writer);
+    rbml_w.end_tag();
+}
+
+fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
+                                  rbml_w: &mut Encoder,
+                                  item: &hir::Item,
+                                  index: &mut CrateIndex<'tcx>,
+                                  path: PathElems,
+                                  vis: hir::Visibility) {
+    let tcx = ecx.tcx;
 
     debug!("encoding info for item at {}",
            tcx.sess.codemap().span_to_string(item.span));
 
-    let def_id = DefId::local(item.id);
-    let stab = stability::lookup(tcx, DefId::local(item.id));
+    let def_id = ecx.tcx.map.local_def_id(item.id);
+    let stab = stability::lookup(tcx, ecx.tcx.map.local_def_id(item.id));
 
     match item.node {
-      ast::ItemStatic(_, m, _) => {
-        add_to_index(item, rbml_w, index);
+      hir::ItemStatic(_, m, _) => {
+        index.record(def_id, rbml_w);
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
-        if m == ast::MutMutable {
+        encode_def_id_and_key(ecx, rbml_w, def_id);
+        if m == hir::MutMutable {
             encode_family(rbml_w, 'b');
         } else {
             encode_family(rbml_w, 'c');
         }
-        encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
+        encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
         encode_symbol(ecx, rbml_w, item.id);
-        encode_name(rbml_w, item.ident.name);
+        encode_name(rbml_w, item.name);
         encode_path(rbml_w, path);
         encode_visibility(rbml_w, vis);
         encode_stability(rbml_w, stab);
         encode_attributes(rbml_w, &item.attrs);
         rbml_w.end_tag();
       }
-      ast::ItemConst(_, _) => {
-        add_to_index(item, rbml_w, index);
+      hir::ItemConst(_, _) => {
+        index.record(def_id, rbml_w);
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
+        encode_def_id_and_key(ecx, rbml_w, def_id);
         encode_family(rbml_w, 'C');
-        encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
-        encode_name(rbml_w, item.ident.name);
+        encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
+        encode_name(rbml_w, item.name);
         encode_path(rbml_w, path);
         encode_attributes(rbml_w, &item.attrs);
         encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
@@ -1035,18 +944,18 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_stability(rbml_w, stab);
         rbml_w.end_tag();
       }
-      ast::ItemFn(ref decl, _, constness, _, ref generics, _) => {
-        add_to_index(item, rbml_w, index);
+      hir::ItemFn(ref decl, _, constness, _, ref generics, _) => {
+        index.record(def_id, rbml_w);
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
+        encode_def_id_and_key(ecx, rbml_w, def_id);
         encode_family(rbml_w, FN_FAMILY);
         let tps_len = generics.ty_params.len();
-        encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
-        encode_name(rbml_w, item.ident.name);
+        encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
+        encode_name(rbml_w, item.name);
         encode_path(rbml_w, path);
         encode_attributes(rbml_w, &item.attrs);
         let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs);
-        if needs_inline || constness == ast::Constness::Const {
+        if needs_inline || constness == hir::Constness::Const {
             encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
         }
         if tps_len == 0 {
@@ -1058,59 +967,59 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_method_argument_names(rbml_w, &**decl);
         rbml_w.end_tag();
       }
-      ast::ItemMod(ref m) => {
-        add_to_index(item, rbml_w, index);
+      hir::ItemMod(ref m) => {
+        index.record(def_id, rbml_w);
         encode_info_for_mod(ecx,
                             rbml_w,
                             m,
                             &item.attrs,
                             item.id,
                             path,
-                            item.ident.name,
+                            item.name,
                             item.vis);
       }
-      ast::ItemForeignMod(ref fm) => {
-        add_to_index(item, rbml_w, index);
+      hir::ItemForeignMod(ref fm) => {
+        index.record(def_id, rbml_w);
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
+        encode_def_id_and_key(ecx, rbml_w, def_id);
         encode_family(rbml_w, 'n');
-        encode_name(rbml_w, item.ident.name);
+        encode_name(rbml_w, item.name);
         encode_path(rbml_w, path);
 
         // Encode all the items in this module.
         for foreign_item in &fm.items {
             rbml_w.wr_tagged_u64(tag_mod_child,
-                                 def_to_u64(DefId::local(foreign_item.id)));
+                                 def_to_u64(ecx.tcx.map.local_def_id(foreign_item.id)));
         }
         encode_visibility(rbml_w, vis);
         encode_stability(rbml_w, stab);
         rbml_w.end_tag();
       }
-      ast::ItemTy(..) => {
-        add_to_index(item, rbml_w, index);
+      hir::ItemTy(..) => {
+        index.record(def_id, rbml_w);
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
+        encode_def_id_and_key(ecx, rbml_w, def_id);
         encode_family(rbml_w, 'y');
-        encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
-        encode_name(rbml_w, item.ident.name);
+        encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
+        encode_name(rbml_w, item.name);
         encode_path(rbml_w, path);
         encode_visibility(rbml_w, vis);
         encode_stability(rbml_w, stab);
         rbml_w.end_tag();
       }
-      ast::ItemEnum(ref enum_definition, _) => {
-        add_to_index(item, rbml_w, index);
+      hir::ItemEnum(ref enum_definition, _) => {
+        index.record(def_id, rbml_w);
 
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
+        encode_def_id_and_key(ecx, rbml_w, def_id);
         encode_family(rbml_w, 't');
         encode_item_variances(rbml_w, ecx, item.id);
-        encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
-        encode_name(rbml_w, item.ident.name);
+        encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
+        encode_name(rbml_w, item.name);
         encode_attributes(rbml_w, &item.attrs);
         encode_repr_attrs(rbml_w, ecx, &item.attrs);
         for v in &enum_definition.variants {
-            encode_variant_id(rbml_w, DefId::local(v.node.id));
+            encode_variant_id(rbml_w, ecx.tcx.map.local_def_id(v.node.data.id()));
         }
         encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
         encode_path(rbml_w, path);
@@ -1128,25 +1037,21 @@ fn encode_info_for_item(ecx: &EncodeContext,
                                  vis,
                                  index);
       }
-      ast::ItemStruct(ref struct_def, _) => {
+      hir::ItemStruct(ref struct_def, _) => {
         let def = ecx.tcx.lookup_adt_def(def_id);
         let variant = def.struct_variant();
 
-        for field in &variant.fields {
-            encode_field(ecx, rbml_w, field, index);
-        }
-
         /* Index the class*/
-        add_to_index(item, rbml_w, index);
+        index.record(def_id, rbml_w);
 
         /* Now, make an item for the class itself */
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
+        encode_def_id_and_key(ecx, rbml_w, def_id);
         encode_family(rbml_w, 'S');
-        encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
+        encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
 
         encode_item_variances(rbml_w, ecx, item.id);
-        encode_name(rbml_w, item.ident.name);
+        encode_name(rbml_w, item.name);
         encode_attributes(rbml_w, &item.attrs);
         encode_path(rbml_w, path.clone());
         encode_stability(rbml_w, stab);
@@ -1156,53 +1061,59 @@ fn encode_info_for_item(ecx: &EncodeContext,
         /* Encode def_ids for each field and method
          for methods, write all the stuff get_trait_method
         needs to know*/
-        encode_struct_fields(rbml_w, variant, def_id);
+        encode_struct_fields(rbml_w, variant);
 
         encode_inlined_item(ecx, rbml_w, InlinedItemRef::Item(item));
 
         // Encode inherent implementations for this structure.
         encode_inherent_implementations(ecx, rbml_w, def_id);
 
+        if !struct_def.is_struct() {
+            let ctor_did = ecx.tcx.map.local_def_id(struct_def.id());
+            rbml_w.wr_tagged_u64(tag_items_data_item_struct_ctor,
+                                 def_to_u64(ctor_did));
+        }
+
         rbml_w.end_tag();
 
+        for field in &variant.fields {
+            encode_field(ecx, rbml_w, field, index);
+        }
+
         // If this is a tuple-like struct, encode the type of the constructor.
-        match struct_def.ctor_id {
-            Some(ctor_id) => {
-                encode_info_for_struct_ctor(ecx, rbml_w, item.ident.name,
-                                            ctor_id, index, def_id.node);
-            }
-            None => {}
+        if !struct_def.is_struct() {
+            encode_info_for_struct_ctor(ecx, rbml_w, item.name, struct_def.id(), index, item.id);
         }
       }
-      ast::ItemDefaultImpl(unsafety, _) => {
-          add_to_index(item, rbml_w, index);
+      hir::ItemDefaultImpl(unsafety, _) => {
+          index.record(def_id, rbml_w);
           rbml_w.start_tag(tag_items_data_item);
-          encode_def_id(rbml_w, def_id);
+          encode_def_id_and_key(ecx, rbml_w, def_id);
           encode_family(rbml_w, 'd');
-          encode_name(rbml_w, item.ident.name);
+          encode_name(rbml_w, item.name);
           encode_unsafety(rbml_w, unsafety);
 
-          let trait_ref = tcx.impl_trait_ref(DefId::local(item.id)).unwrap();
+          let trait_ref = tcx.impl_trait_ref(ecx.tcx.map.local_def_id(item.id)).unwrap();
           encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
           rbml_w.end_tag();
       }
-      ast::ItemImpl(unsafety, polarity, _, _, ref ty, ref ast_items) => {
+      hir::ItemImpl(unsafety, polarity, _, _, _, ref ast_items) => {
         // We need to encode information about the default methods we
         // have inherited, so we drive this based on the impl structure.
         let impl_items = tcx.impl_items.borrow();
         let items = impl_items.get(&def_id).unwrap();
 
-        add_to_index(item, rbml_w, index);
+        index.record(def_id, rbml_w);
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
+        encode_def_id_and_key(ecx, rbml_w, def_id);
         encode_family(rbml_w, 'i');
-        encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
-        encode_name(rbml_w, item.ident.name);
+        encode_bounds_and_type_for_item(rbml_w, ecx, index, item.id);
+        encode_name(rbml_w, item.name);
         encode_attributes(rbml_w, &item.attrs);
         encode_unsafety(rbml_w, unsafety);
         encode_polarity(rbml_w, polarity);
 
-        match tcx.custom_coerce_unsized_kinds.borrow().get(&DefId::local(item.id)) {
+        match tcx.custom_coerce_unsized_kinds.borrow().get(&ecx.tcx.map.local_def_id(item.id)) {
             Some(&kind) => {
                 rbml_w.start_tag(tag_impl_coerce_unsized_kind);
                 kind.encode(rbml_w);
@@ -1211,13 +1122,6 @@ fn encode_info_for_item(ecx: &EncodeContext,
             None => {}
         }
 
-        match ty.node {
-            ast::TyPath(None, ref path) if path.segments.len() == 1 => {
-                let name = path.segments.last().unwrap().identifier.name;
-                encode_impl_type_basename(rbml_w, name);
-            }
-            _ => {}
-        }
         for &item_def_id in items {
             rbml_w.start_tag(tag_item_impl_item);
             match item_def_id {
@@ -1236,7 +1140,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
             }
             rbml_w.end_tag();
         }
-        if let Some(trait_ref) = tcx.impl_trait_ref(DefId::local(item.id)) {
+        if let Some(trait_ref) = tcx.impl_trait_ref(ecx.tcx.map.local_def_id(item.id)) {
             encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
         }
         encode_path(rbml_w, path.clone());
@@ -1255,15 +1159,11 @@ fn encode_info_for_item(ecx: &EncodeContext,
                 None
             };
 
-            index.push(IndexEntry {
-                node: trait_item_def_id.def_id().node,
-                pos: rbml_w.mark_stable_position(),
-            });
-
             match tcx.impl_or_trait_item(trait_item_def_id.def_id()) {
                 ty::ConstTraitItem(ref associated_const) => {
                     encode_info_for_associated_const(ecx,
                                                      rbml_w,
+                                                     index,
                                                      &*associated_const,
                                                      path.clone(),
                                                      item.id,
@@ -1272,6 +1172,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
                 ty::MethodTraitItem(ref method_type) => {
                     encode_info_for_method(ecx,
                                            rbml_w,
+                                           index,
                                            &**method_type,
                                            path.clone(),
                                            false,
@@ -1281,6 +1182,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
                 ty::TypeTraitItem(ref associated_type) => {
                     encode_info_for_associated_type(ecx,
                                                     rbml_w,
+                                                    index,
                                                     &**associated_type,
                                                     path.clone(),
                                                     item.id,
@@ -1289,10 +1191,10 @@ fn encode_info_for_item(ecx: &EncodeContext,
             }
         }
       }
-      ast::ItemTrait(_, _, _, ref ms) => {
-        add_to_index(item, rbml_w, index);
+      hir::ItemTrait(_, _, _, ref ms) => {
+        index.record(def_id, rbml_w);
         rbml_w.start_tag(tag_items_data_item);
-        encode_def_id(rbml_w, def_id);
+        encode_def_id_and_key(ecx, rbml_w, def_id);
         encode_family(rbml_w, 'I');
         encode_item_variances(rbml_w, ecx, item.id);
         let trait_def = tcx.lookup_trait_def(def_id);
@@ -1301,12 +1203,14 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_paren_sugar(rbml_w, trait_def.paren_sugar);
         encode_defaulted(rbml_w, tcx.trait_has_default_impl(def_id));
         encode_associated_type_names(rbml_w, &trait_def.associated_type_names);
-        encode_generics(rbml_w, ecx, &trait_def.generics, &trait_predicates,
+        encode_generics(rbml_w, ecx, index,
+                        &trait_def.generics, &trait_predicates,
                         tag_item_generics);
-        encode_predicates(rbml_w, ecx, &tcx.lookup_super_predicates(def_id),
+        encode_predicates(rbml_w, ecx, index,
+                          &tcx.lookup_super_predicates(def_id),
                           tag_item_super_predicates);
         encode_trait_ref(rbml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
-        encode_name(rbml_w, item.ident.name);
+        encode_name(rbml_w, item.name);
         encode_attributes(rbml_w, &item.attrs);
         encode_visibility(rbml_w, vis);
         encode_stability(rbml_w, stab);
@@ -1333,9 +1237,6 @@ fn encode_info_for_item(ecx: &EncodeContext,
         }
         encode_path(rbml_w, path.clone());
 
-        // Encode the implementations of this trait.
-        encode_extension_implementations(ecx, rbml_w, def_id);
-
         // Encode inherent implementations for this trait.
         encode_inherent_implementations(ecx, rbml_w, def_id);
 
@@ -1346,11 +1247,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         for (i, &item_def_id) in r.iter().enumerate() {
             assert_eq!(item_def_id.def_id().krate, LOCAL_CRATE);
 
-            index.push(IndexEntry {
-                node: item_def_id.def_id().node,
-                pos: rbml_w.mark_stable_position(),
-            });
-
+            index.record(item_def_id.def_id(), rbml_w);
             rbml_w.start_tag(tag_items_data_item);
 
             encode_parent_item(rbml_w, def_id);
@@ -1364,27 +1261,24 @@ fn encode_info_for_item(ecx: &EncodeContext,
             match trait_item_type {
                 ty::ConstTraitItem(associated_const) => {
                     encode_name(rbml_w, associated_const.name);
-                    encode_def_id(rbml_w, associated_const.def_id);
+                    encode_def_id_and_key(ecx, rbml_w, associated_const.def_id);
                     encode_visibility(rbml_w, associated_const.vis);
 
-                    encode_provided_source(rbml_w, associated_const.default);
-
                     let elem = ast_map::PathName(associated_const.name);
                     encode_path(rbml_w,
                                 path.clone().chain(Some(elem)));
 
-                    encode_item_sort(rbml_w, 'C');
                     encode_family(rbml_w, 'C');
 
-                    encode_bounds_and_type_for_item(rbml_w, ecx,
-                                                    associated_const.def_id.local_id());
+                    encode_bounds_and_type_for_item(rbml_w, ecx, index,
+                                                    ecx.local_id(associated_const.def_id));
 
                     is_nonstatic_method = false;
                 }
                 ty::MethodTraitItem(method_ty) => {
                     let method_def_id = item_def_id.def_id();
 
-                    encode_method_ty_fields(ecx, rbml_w, &*method_ty);
+                    encode_method_ty_fields(ecx, rbml_w, index, &*method_ty);
 
                     let elem = ast_map::PathName(method_ty.name);
                     encode_path(rbml_w,
@@ -1400,14 +1294,15 @@ fn encode_info_for_item(ecx: &EncodeContext,
                                           METHOD_FAMILY);
                         }
                     }
-                    encode_bounds_and_type_for_item(rbml_w, ecx, method_def_id.local_id());
+                    encode_bounds_and_type_for_item(rbml_w, ecx, index,
+                                                    ecx.local_id(method_def_id));
 
                     is_nonstatic_method = method_ty.explicit_self !=
                         ty::StaticExplicitSelfCategory;
                 }
                 ty::TypeTraitItem(associated_type) => {
                     encode_name(rbml_w, associated_type.name);
-                    encode_def_id(rbml_w, associated_type.def_id);
+                    encode_def_id_and_key(ecx, rbml_w, associated_type.def_id);
 
                     let elem = ast_map::PathName(associated_type.name);
                     encode_path(rbml_w,
@@ -1424,23 +1319,27 @@ fn encode_info_for_item(ecx: &EncodeContext,
                 }
             }
 
-            encode_parent_sort(rbml_w, 't');
-
             let trait_item = &*ms[i];
             encode_attributes(rbml_w, &trait_item.attrs);
             match trait_item.node {
-                ast::ConstTraitItem(_, _) => {
+                hir::ConstTraitItem(_, ref default) => {
+                    if default.is_some() {
+                        encode_item_sort(rbml_w, 'C');
+                    } else {
+                        encode_item_sort(rbml_w, 'c');
+                    }
+
                     encode_inlined_item(ecx, rbml_w,
                                         InlinedItemRef::TraitItem(def_id, trait_item));
                 }
-                ast::MethodTraitItem(ref sig, ref body) => {
+                hir::MethodTraitItem(ref sig, ref body) => {
                     // If this is a static method, we've already
                     // encoded this.
                     if is_nonstatic_method {
                         // FIXME: I feel like there is something funny
                         // going on.
-                        encode_bounds_and_type_for_item(rbml_w, ecx,
-                            item_def_id.def_id().local_id());
+                        encode_bounds_and_type_for_item(rbml_w, ecx, index,
+                                                        ecx.local_id(item_def_id.def_id()));
                     }
 
                     if body.is_some() {
@@ -1453,82 +1352,107 @@ fn encode_info_for_item(ecx: &EncodeContext,
                     encode_method_argument_names(rbml_w, &sig.decl);
                 }
 
-                ast::TypeTraitItem(..) => {}
+                hir::TypeTraitItem(..) => {}
             }
 
             rbml_w.end_tag();
         }
       }
-      ast::ItemExternCrate(_) | ast::ItemUse(_) => {
+      hir::ItemExternCrate(_) | hir::ItemUse(_) => {
         // these are encoded separately
       }
     }
 }
 
-fn encode_info_for_foreign_item(ecx: &EncodeContext,
-                                rbml_w: &mut Encoder,
-                                nitem: &ast::ForeignItem,
-                                index: &mut Vec<IndexEntry>,
-                                path: PathElems,
-                                abi: abi::Abi) {
-    index.push(IndexEntry {
-        node: nitem.id,
-        pos: rbml_w.mark_stable_position(),
-    });
+fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
+                                          rbml_w: &mut Encoder,
+                                          nitem: &hir::ForeignItem,
+                                          index: &mut CrateIndex<'tcx>,
+                                          path: PathElems,
+                                          abi: abi::Abi) {
+    let def_id = ecx.tcx.map.local_def_id(nitem.id);
 
+    index.record(def_id, rbml_w);
     rbml_w.start_tag(tag_items_data_item);
-    encode_def_id(rbml_w, DefId::local(nitem.id));
+    encode_def_id_and_key(ecx, rbml_w, def_id);
     encode_visibility(rbml_w, nitem.vis);
     match nitem.node {
-      ast::ForeignItemFn(ref fndecl, _) => {
+      hir::ForeignItemFn(ref fndecl, _) => {
         encode_family(rbml_w, FN_FAMILY);
-        encode_bounds_and_type_for_item(rbml_w, ecx, nitem.id);
-        encode_name(rbml_w, nitem.ident.name);
+        encode_bounds_and_type_for_item(rbml_w, ecx, index, nitem.id);
+        encode_name(rbml_w, nitem.name);
         if abi == abi::RustIntrinsic || abi == abi::PlatformIntrinsic {
             encode_inlined_item(ecx, rbml_w, InlinedItemRef::Foreign(nitem));
         }
         encode_attributes(rbml_w, &*nitem.attrs);
-        let stab = stability::lookup(ecx.tcx, DefId::local(nitem.id));
+        let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
         encode_stability(rbml_w, stab);
         encode_symbol(ecx, rbml_w, nitem.id);
         encode_method_argument_names(rbml_w, &*fndecl);
       }
-      ast::ForeignItemStatic(_, mutbl) => {
+      hir::ForeignItemStatic(_, mutbl) => {
         if mutbl {
             encode_family(rbml_w, 'b');
         } else {
             encode_family(rbml_w, 'c');
         }
-        encode_bounds_and_type_for_item(rbml_w, ecx, nitem.id);
+        encode_bounds_and_type_for_item(rbml_w, ecx, index, nitem.id);
         encode_attributes(rbml_w, &*nitem.attrs);
-        let stab = stability::lookup(ecx.tcx, DefId::local(nitem.id));
+        let stab = stability::lookup(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
         encode_stability(rbml_w, stab);
         encode_symbol(ecx, rbml_w, nitem.id);
-        encode_name(rbml_w, nitem.ident.name);
+        encode_name(rbml_w, nitem.name);
       }
     }
     encode_path(rbml_w, path);
     rbml_w.end_tag();
 }
 
-fn my_visit_expr(_e: &ast::Expr) { }
-
-fn my_visit_item(i: &ast::Item,
+fn my_visit_expr(expr: &hir::Expr,
                  rbml_w: &mut Encoder,
                  ecx: &EncodeContext,
-                 index: &mut Vec<IndexEntry>) {
+                 index: &mut CrateIndex) {
+    match expr.node {
+        hir::ExprClosure(..) => {
+            let def_id = ecx.tcx.map.local_def_id(expr.id);
+
+            index.record(def_id, rbml_w);
+
+            rbml_w.start_tag(tag_items_data_item);
+            encode_def_id_and_key(ecx, rbml_w, def_id);
+
+            rbml_w.start_tag(tag_items_closure_ty);
+            write_closure_type(ecx, rbml_w, &ecx.tcx.tables.borrow().closure_tys[&def_id]);
+            rbml_w.end_tag();
+
+            rbml_w.start_tag(tag_items_closure_kind);
+            ecx.tcx.closure_kind(def_id).encode(rbml_w).unwrap();
+            rbml_w.end_tag();
+
+            ecx.tcx.map.with_path(expr.id, |path| encode_path(rbml_w, path));
+
+            rbml_w.end_tag();
+        }
+        _ => { }
+    }
+}
+
+fn my_visit_item<'a, 'tcx>(i: &hir::Item,
+                           rbml_w: &mut Encoder,
+                           ecx: &EncodeContext<'a, 'tcx>,
+                           index: &mut CrateIndex<'tcx>) {
     ecx.tcx.map.with_path(i.id, |path| {
         encode_info_for_item(ecx, rbml_w, i, index, path, i.vis);
     });
 }
 
-fn my_visit_foreign_item(ni: &ast::ForeignItem,
-                         rbml_w: &mut Encoder,
-                         ecx: &EncodeContext,
-                         index: &mut Vec<IndexEntry>) {
+fn my_visit_foreign_item<'a, 'tcx>(ni: &hir::ForeignItem,
+                                   rbml_w: &mut Encoder,
+                                   ecx: &EncodeContext<'a, 'tcx>,
+                                   index: &mut CrateIndex<'tcx>) {
     debug!("writing foreign item {}::{}",
             ecx.tcx.map.path_to_string(ni.id),
-            ni.ident);
+            ni.name);
 
     let abi = ecx.tcx.map.get_foreign_abi(ni.id);
     ecx.tcx.map.with_path(ni.id, |path| {
@@ -1541,40 +1465,35 @@ fn my_visit_foreign_item(ni: &ast::ForeignItem,
 struct EncodeVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
     rbml_w_for_visit_item: &'a mut Encoder<'b>,
     ecx: &'a EncodeContext<'c,'tcx>,
-    index: &'a mut Vec<IndexEntry>,
+    index: &'a mut CrateIndex<'tcx>,
 }
 
 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for EncodeVisitor<'a, 'b, 'c, 'tcx> {
-    fn visit_expr(&mut self, ex: &ast::Expr) {
+    fn visit_expr(&mut self, ex: &hir::Expr) {
         visit::walk_expr(self, ex);
-        my_visit_expr(ex);
+        my_visit_expr(ex, self.rbml_w_for_visit_item, self.ecx, self.index);
     }
-    fn visit_item(&mut self, i: &ast::Item) {
+    fn visit_item(&mut self, i: &hir::Item) {
         visit::walk_item(self, i);
-        my_visit_item(i,
-                      self.rbml_w_for_visit_item,
-                      self.ecx,
-                      self.index);
+        my_visit_item(i, self.rbml_w_for_visit_item, self.ecx, self.index);
     }
-    fn visit_foreign_item(&mut self, ni: &ast::ForeignItem) {
+    fn visit_foreign_item(&mut self, ni: &hir::ForeignItem) {
         visit::walk_foreign_item(self, ni);
-        my_visit_foreign_item(ni,
-                              self.rbml_w_for_visit_item,
-                              self.ecx,
-                              self.index);
+        my_visit_foreign_item(ni, self.rbml_w_for_visit_item, self.ecx, self.index);
     }
 }
 
-fn encode_info_for_items(ecx: &EncodeContext,
-                         rbml_w: &mut Encoder,
-                         krate: &ast::Crate)
-                         -> Vec<IndexEntry> {
-    let mut index = Vec::new();
+fn encode_info_for_items<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
+                                   rbml_w: &mut Encoder,
+                                   krate: &hir::Crate)
+                                   -> CrateIndex<'tcx> {
+    let mut index = CrateIndex {
+        items: IndexData::new(ecx.tcx.map.num_local_def_ids()),
+        xrefs: FnvHashMap()
+    };
     rbml_w.start_tag(tag_items_data);
-    index.push(IndexEntry {
-        node: CRATE_NODE_ID,
-        pos: rbml_w.mark_stable_position(),
-    });
+
+    index.record(DefId::local(CRATE_DEF_INDEX), rbml_w);
     encode_info_for_mod(ecx,
                         rbml_w,
                         &krate.module,
@@ -1582,7 +1501,7 @@ fn encode_info_for_items(ecx: &EncodeContext,
                         CRATE_NODE_ID,
                         [].iter().cloned().chain(LinkedPath::empty()),
                         syntax::parse::token::special_idents::invalid.name,
-                        ast::Public);
+                        hir::Public);
 
     visit::walk_crate(&mut EncodeVisitor {
         index: &mut index,
@@ -1594,13 +1513,9 @@ fn encode_info_for_items(ecx: &EncodeContext,
     index
 }
 
-
-
-
-fn encode_index(rbml_w: &mut Encoder, index: Vec<IndexEntry>)
-{
+fn encode_item_index(rbml_w: &mut Encoder, index: IndexData) {
     rbml_w.start_tag(tag_index);
-    index::write_index(index, rbml_w.writer);
+    index.write_index(rbml_w.writer);
     rbml_w.end_tag();
 }
 
@@ -1644,10 +1559,10 @@ fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
     rbml_w.end_tag();
 }
 
-fn encode_unsafety(rbml_w: &mut Encoder, unsafety: ast::Unsafety) {
+fn encode_unsafety(rbml_w: &mut Encoder, unsafety: hir::Unsafety) {
     let byte: u8 = match unsafety {
-        ast::Unsafety::Normal => 0,
-        ast::Unsafety::Unsafe => 1,
+        hir::Unsafety::Normal => 0,
+        hir::Unsafety::Unsafe => 1,
     };
     rbml_w.wr_tagged_u8(tag_unsafety, byte);
 }
@@ -1670,10 +1585,10 @@ fn encode_associated_type_names(rbml_w: &mut Encoder, names: &[Name]) {
     rbml_w.end_tag();
 }
 
-fn encode_polarity(rbml_w: &mut Encoder, polarity: ast::ImplPolarity) {
+fn encode_polarity(rbml_w: &mut Encoder, polarity: hir::ImplPolarity) {
     let byte: u8 = match polarity {
-        ast::ImplPolarity::Positive => 0,
-        ast::ImplPolarity::Negative => 1,
+        hir::ImplPolarity::Positive => 0,
+        hir::ImplPolarity::Negative => 1,
     };
     rbml_w.wr_tagged_u8(tag_polarity, byte);
 }
@@ -1714,12 +1629,12 @@ fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
 fn encode_lang_items(ecx: &EncodeContext, rbml_w: &mut Encoder) {
     rbml_w.start_tag(tag_lang_items);
 
-    for (i, &def_id) in ecx.tcx.lang_items.items() {
-        if let Some(id) = def_id {
-            if id.is_local() {
+    for (i, &opt_def_id) in ecx.tcx.lang_items.items() {
+        if let Some(def_id) = opt_def_id {
+            if def_id.is_local() {
                 rbml_w.start_tag(tag_lang_items_item);
                 rbml_w.wr_tagged_u32(tag_lang_items_item_id, i as u32);
-                rbml_w.wr_tagged_u32(tag_lang_items_item_node_id, id.node as u32);
+                rbml_w.wr_tagged_u32(tag_lang_items_item_index, def_id.index.as_u32());
                 rbml_w.end_tag();
             }
         }
@@ -1753,7 +1668,10 @@ fn encode_native_libraries(ecx: &EncodeContext, rbml_w: &mut Encoder) {
 
 fn encode_plugin_registrar_fn(ecx: &EncodeContext, rbml_w: &mut Encoder) {
     match ecx.tcx.sess.plugin_registrar_fn.get() {
-        Some(id) => { rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
+        Some(id) => {
+            let def_id = ecx.tcx.map.local_def_id(id);
+            rbml_w.wr_tagged_u32(tag_plugin_registrar_fn, def_id.index.as_u32());
+        }
         None => {}
     }
 }
@@ -1782,12 +1700,12 @@ fn encode_codemap(ecx: &EncodeContext, rbml_w: &mut Encoder) {
 
 /// Serialize the text of the exported macros
 fn encode_macro_defs(rbml_w: &mut Encoder,
-                     krate: &ast::Crate) {
+                     krate: &hir::Crate) {
     rbml_w.start_tag(tag_macro_defs);
     for def in &krate.exported_macros {
         rbml_w.start_tag(tag_macro_def);
 
-        encode_name(rbml_w, def.ident.name);
+        encode_name(rbml_w, def.name);
         encode_attributes(rbml_w, &def.attrs);
 
         rbml_w.wr_tagged_str(tag_macro_def_body,
@@ -1798,97 +1716,90 @@ fn encode_macro_defs(rbml_w: &mut Encoder,
     rbml_w.end_tag();
 }
 
-fn encode_struct_field_attrs(rbml_w: &mut Encoder, krate: &ast::Crate) {
-    struct StructFieldVisitor<'a, 'b:'a> {
-        rbml_w: &'a mut Encoder<'b>,
+fn encode_struct_field_attrs(ecx: &EncodeContext,
+                             rbml_w: &mut Encoder,
+                             krate: &hir::Crate) {
+    struct StructFieldVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
+        ecx: &'a EncodeContext<'b, 'tcx>,
+        rbml_w: &'a mut Encoder<'c>,
     }
 
-    impl<'a, 'b, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b> {
-        fn visit_struct_field(&mut self, field: &ast::StructField) {
+    impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b, 'c, 'tcx> {
+        fn visit_struct_field(&mut self, field: &hir::StructField) {
             self.rbml_w.start_tag(tag_struct_field);
-            self.rbml_w.wr_tagged_u32(tag_struct_field_id, field.node.id);
+            let def_id = self.ecx.tcx.map.local_def_id(field.node.id);
+            encode_def_id(self.rbml_w, def_id);
             encode_attributes(self.rbml_w, &field.node.attrs);
             self.rbml_w.end_tag();
         }
     }
 
     rbml_w.start_tag(tag_struct_fields);
-    visit::walk_crate(&mut StructFieldVisitor {
-        rbml_w: rbml_w
-    }, krate);
+    visit::walk_crate(&mut StructFieldVisitor { ecx: ecx, rbml_w: rbml_w }, krate);
     rbml_w.end_tag();
 }
 
 
 
-struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
-    ecx: &'a EncodeContext<'b, 'tcx>,
-    rbml_w: &'a mut Encoder<'c>,
+struct ImplVisitor<'a, 'tcx:'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+    impls: FnvHashMap<DefId, Vec<DefId>>
 }
 
-impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
-    fn visit_item(&mut self, item: &ast::Item) {
-        if let ast::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
-            let def_id = self.ecx.tcx.def_map.borrow().get(&trait_ref.ref_id).unwrap().def_id();
-
-            // Load eagerly if this is an implementation of the Drop trait
-            // or if the trait is not defined in this crate.
-            if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
-                    def_id.krate != LOCAL_CRATE {
-                self.rbml_w.start_tag(tag_impls_impl);
-                encode_def_id(self.rbml_w, DefId::local(item.id));
-                self.rbml_w.wr_tagged_u64(tag_impls_impl_trait_def_id, def_to_u64(def_id));
-                self.rbml_w.end_tag();
+impl<'a, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'tcx> {
+    fn visit_item(&mut self, item: &hir::Item) {
+        if let hir::ItemImpl(..) = item.node {
+            let impl_id = self.tcx.map.local_def_id(item.id);
+            if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) {
+                self.impls.entry(trait_ref.def_id)
+                    .or_insert(vec![])
+                    .push(impl_id);
             }
         }
         visit::walk_item(self, item);
     }
 }
 
-/// Encodes implementations that are eagerly loaded.
-///
-/// None of this is necessary in theory; we can load all implementations
-/// lazily. However, in two cases the optimizations to lazily load
-/// implementations are not yet implemented. These two cases, which require us
-/// to load implementations eagerly, are:
-///
-/// * Destructors (implementations of the Drop trait).
-///
-/// * Implementations of traits not defined in this crate.
+/// Encodes an index, mapping each trait to its (local) implementations.
 fn encode_impls<'a>(ecx: &'a EncodeContext,
-                    krate: &ast::Crate,
+                    krate: &hir::Crate,
                     rbml_w: &'a mut Encoder) {
-    rbml_w.start_tag(tag_impls);
+    let mut visitor = ImplVisitor {
+        tcx: ecx.tcx,
+        impls: FnvHashMap()
+    };
+    visit::walk_crate(&mut visitor, krate);
 
-    {
-        let mut visitor = ImplVisitor {
-            ecx: ecx,
-            rbml_w: rbml_w,
-        };
-        visit::walk_crate(&mut visitor, krate);
+    rbml_w.start_tag(tag_impls);
+    for (trait_, trait_impls) in visitor.impls {
+        rbml_w.start_tag(tag_impls_trait);
+        encode_def_id(rbml_w, trait_);
+        for impl_ in trait_impls {
+            rbml_w.wr_tagged_u64(tag_impls_trait_impl, def_to_u64(impl_));
+        }
+        rbml_w.end_tag();
     }
-
     rbml_w.end_tag();
 }
 
 fn encode_misc_info(ecx: &EncodeContext,
-                    krate: &ast::Crate,
+                    krate: &hir::Crate,
                     rbml_w: &mut Encoder) {
     rbml_w.start_tag(tag_misc_info);
     rbml_w.start_tag(tag_misc_info_crate_items);
     for item in &krate.module.items {
         rbml_w.wr_tagged_u64(tag_mod_child,
-                             def_to_u64(DefId::local(item.id)));
+                             def_to_u64(ecx.tcx.map.local_def_id(item.id)));
 
         each_auxiliary_node_id(&**item, |auxiliary_node_id| {
             rbml_w.wr_tagged_u64(tag_mod_child,
-                                 def_to_u64(DefId::local(auxiliary_node_id)));
+                                 def_to_u64(ecx.tcx.map.local_def_id(auxiliary_node_id)));
             true
         });
     }
 
     // Encode reexports for the root module.
-    encode_reexports(ecx, rbml_w, 0, [].iter().cloned().chain(LinkedPath::empty()));
+    encode_reexports(ecx, rbml_w, 0);
 
     rbml_w.end_tag();
     rbml_w.end_tag();
@@ -1902,8 +1813,9 @@ fn encode_misc_info(ecx: &EncodeContext,
 // definition (as that's not defined in this crate).
 fn encode_reachable(ecx: &EncodeContext, rbml_w: &mut Encoder) {
     rbml_w.start_tag(tag_reachable_ids);
-    for id in ecx.reachable {
-        rbml_w.wr_tagged_u32(tag_reachable_id, *id);
+    for &id in ecx.reachable {
+        let def_id = ecx.tcx.map.local_def_id(id);
+        rbml_w.wr_tagged_u32(tag_reachable_id, def_id.index.as_u32());
     }
     rbml_w.end_tag();
 }
@@ -1923,6 +1835,10 @@ fn encode_hash(rbml_w: &mut Encoder, hash: &Svh) {
     rbml_w.wr_tagged_str(tag_crate_hash, hash.as_str());
 }
 
+fn encode_rustc_version(rbml_w: &mut Encoder) {
+    rbml_w.wr_tagged_str(tag_rustc_version, &rustc_version());
+}
+
 fn encode_crate_name(rbml_w: &mut Encoder, crate_name: &str) {
     rbml_w.wr_tagged_str(tag_crate_crate_name, crate_name);
 }
@@ -1956,7 +1872,7 @@ fn encode_dylib_dependency_formats(rbml_w: &mut Encoder, ecx: &EncodeContext) {
 #[allow(non_upper_case_globals)]
 pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2 ];
 
-pub fn encode_metadata(parms: EncodeParams, krate: &ast::Crate) -> Vec<u8> {
+pub fn encode_metadata(parms: EncodeParams, krate: &hir::Crate) -> Vec<u8> {
     let mut wr = Cursor::new(Vec::new());
     encode_metadata_inner(&mut wr, parms, krate);
 
@@ -1995,7 +1911,7 @@ pub fn encode_metadata(parms: EncodeParams, krate: &ast::Crate) -> Vec<u8> {
 
 fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>,
                          parms: EncodeParams,
-                         krate: &ast::Crate) {
+                         krate: &hir::Crate) {
     struct Stats {
         attr_bytes: u64,
         dep_bytes: u64,
@@ -2008,6 +1924,7 @@ fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>,
         misc_bytes: u64,
         item_bytes: u64,
         index_bytes: u64,
+        xref_bytes: u64,
         zero_bytes: u64,
         total_bytes: u64,
     }
@@ -2023,6 +1940,7 @@ fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>,
         misc_bytes: 0,
         item_bytes: 0,
         index_bytes: 0,
+        xref_bytes: 0,
         zero_bytes: 0,
         total_bytes: 0,
     };
@@ -2051,6 +1969,7 @@ fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>,
 
     let mut rbml_w = Encoder::new(wr);
 
+    encode_rustc_version(&mut rbml_w);
     encode_crate_name(&mut rbml_w, &ecx.link_meta.crate_name);
     encode_crate_triple(&mut rbml_w, &tcx.sess.opts.target_triple);
     encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);
@@ -2103,15 +2022,19 @@ fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>,
     // Encode and index the items.
     rbml_w.start_tag(tag_items);
     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
-    let items_index = encode_info_for_items(&ecx, &mut rbml_w, krate);
+    let index = encode_info_for_items(&ecx, &mut rbml_w, krate);
     stats.item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
     rbml_w.end_tag();
 
     i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
-    encode_index(&mut rbml_w, items_index);
+    encode_item_index(&mut rbml_w, index.items);
     stats.index_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
 
-    encode_struct_field_attrs(&mut rbml_w, krate);
+    i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
+    encode_xrefs(&ecx, &mut rbml_w, index.xrefs);
+    stats.xref_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
+
+    encode_struct_field_attrs(&ecx, &mut rbml_w, krate);
 
     stats.total_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
 
@@ -2134,13 +2057,14 @@ fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>,
         println!("            misc bytes: {}", stats.misc_bytes);
         println!("            item bytes: {}", stats.item_bytes);
         println!("           index bytes: {}", stats.index_bytes);
+        println!("            xref bytes: {}", stats.xref_bytes);
         println!("            zero bytes: {}", stats.zero_bytes);
         println!("           total bytes: {}", stats.total_bytes);
     }
 }
 
 // Get the encoded string for a type
-pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> String {
+pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> Vec<u8> {
     let mut wr = Cursor::new(Vec::new());
     tyencode::enc_ty(&mut Encoder::new(&mut wr), &tyencode::ctxt {
         diag: tcx.sess.diagnostic(),
@@ -2148,5 +2072,5 @@ pub fn encoded_ty<'tcx>(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>) -> String {
         tcx: tcx,
         abbrevs: &RefCell::new(FnvHashMap())
     }, t);
-    String::from_utf8(wr.into_inner()).unwrap()
+    wr.into_inner()
 }
index b02a9022a7a6e835f37f24592cb8ab24a34afce9..60bbdaddd751607c7e75c1ffeade30db3d440852 100644 (file)
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use middle::def_id::{DefId, DefIndex};
+use rbml;
 use std::io::{Cursor, Write};
 use std::slice;
 use std::u32;
-use syntax::ast::NodeId;
 
-#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]
-pub struct IndexEntry {
-    pub node: NodeId,
-    pub pos: u64
-}
-
-#[derive(Debug)]
-pub struct IndexArrayEntry {
-    bits: u32,
-    first_pos: u32
+/// As part of the metadata, we generate an index that stores, for
+/// each DefIndex, the position of the corresponding RBML document (if
+/// any).  This is just a big `[u32]` slice, where an entry of
+/// `u32::MAX` indicates that there is no RBML document. This little
+/// struct just stores the offsets within the metadata of the start
+/// and end of this slice. These are actually part of an RBML
+/// document, but for looking things up in the metadata, we just
+/// discard the RBML positioning and jump directly to the data.
+pub struct Index {
+    data_start: usize,
+    data_end: usize,
 }
 
-impl IndexArrayEntry {
-    fn encode_to<W: Write>(&self, b: &mut W) {
-        write_be_u32(b, self.bits);
-        write_be_u32(b, self.first_pos);
+impl Index {
+    /// Given the RBML doc representing the index, save the offests
+    /// for later.
+    pub fn from_rbml(index: rbml::Doc) -> Index {
+        Index { data_start: index.start, data_end: index.end }
     }
 
-    fn decode_from(b: &[u32]) -> Self {
-        IndexArrayEntry {
-            bits: b[0].to_be(),
-            first_pos: b[1].to_be()
+    /// Given the metadata, extract out the offset of a particular
+    /// DefIndex (if any).
+    #[inline(never)]
+    pub fn lookup_item(&self, bytes: &[u8], def_index: DefIndex) -> Option<u32> {
+        let words = bytes_to_words(&bytes[self.data_start..self.data_end]);
+        let index = def_index.as_usize();
+
+        debug!("lookup_item: index={:?} words.len={:?}",
+               index, words.len());
+
+        let position = u32::from_be(words[index]);
+        if position == u32::MAX {
+            debug!("lookup_item: position=u32::MAX");
+            None
+        } else {
+            debug!("lookup_item: position={:?}", position);
+            Some(position)
         }
     }
 }
 
-/// The Item Index
-///
-/// This index maps the NodeId of each item to its location in the
-/// metadata.
-///
-/// The index is a sparse bit-vector consisting of a index-array
-/// and a position-array. Each entry in the index-array handles 32 nodes.
-/// The first word is a bit-array consisting of the nodes that hold items,
-/// the second is the index of the first of the items in the position-array.
-/// If there is a large set of non-item trailing nodes, they can be omitted
-/// from the index-array.
-///
-/// The index is serialized as an array of big-endian 32-bit words.
-/// The first word is the number of items in the position-array.
-/// Then, for each item, its position in the metadata follows.
-/// After that the index-array is stored.
-///
-/// struct index {
-///     u32 item_count;
-///     u32 items[self.item_count];
-///     struct { u32 bits; u32 offset; } positions[..];
-/// }
-pub struct Index {
-    position_start: usize,
-    index_start: usize,
-    index_end: usize,
+/// While we are generating the metadata, we also track the position
+/// of each DefIndex. It is not required that all definitions appear
+/// in the metadata, nor that they are serialized in order, and
+/// therefore we first allocate the vector here and fill it with
+/// `u32::MAX`. Whenever an index is visited, we fill in the
+/// appropriate spot by calling `record_position`. We should never
+/// visit the same index twice.
+pub struct IndexData {
+    positions: Vec<u32>,
 }
 
-pub fn write_index(mut entries: Vec<IndexEntry>, buf: &mut Cursor<Vec<u8>>) {
-    assert!(entries.len() < u32::MAX as usize);
-    entries.sort();
+impl IndexData {
+    pub fn new(max_index: usize) -> IndexData {
+        IndexData {
+            positions: vec![u32::MAX; max_index]
+        }
+    }
+
+    pub fn record(&mut self, def_id: DefId, position: u64) {
+        assert!(def_id.is_local());
+        self.record_index(def_id.index, position)
+    }
+
+    pub fn record_index(&mut self, item: DefIndex, position: u64) {
+        let item = item.as_usize();
+
+        assert!(position < (u32::MAX as u64));
+        let position = position as u32;
 
-    let mut last_entry = IndexArrayEntry { bits: 0, first_pos: 0 };
+        assert!(self.positions[item] == u32::MAX,
+                "recorded position for item {:?} twice, first at {:?} and now at {:?}",
+                item, self.positions[item], position);
 
-    write_be_u32(buf, entries.len() as u32);
-    for &IndexEntry { pos, .. } in &entries {
-        assert!(pos < u32::MAX as u64);
-        write_be_u32(buf, pos as u32);
+        self.positions[item] = position;
     }
 
-    let mut pos_in_index_array = 0;
-    for (i, &IndexEntry { node, .. }) in entries.iter().enumerate() {
-        let (x, s) = (node / 32 as u32, node % 32 as u32);
-        while x > pos_in_index_array {
-            pos_in_index_array += 1;
-            last_entry.encode_to(buf);
-            last_entry = IndexArrayEntry { bits: 0, first_pos: i as u32 };
+    pub fn write_index(&self, buf: &mut Cursor<Vec<u8>>) {
+        for &position in &self.positions {
+            write_be_u32(buf, position);
         }
-        last_entry.bits |= 1<<s;
     }
-    last_entry.encode_to(buf);
+}
 
-    info!("write_index: {} items, {} array entries",
-          entries.len(), pos_in_index_array);
+/// A dense index with integer keys. Different API from IndexData (should
+/// these be merged?)
+pub struct DenseIndex {
+    start: usize,
+    end: usize
 }
 
-impl Index {
-    fn lookup_index(&self, index: &[u32], i: u32) -> Option<IndexArrayEntry> {
-        let ix = (i as usize)*2;
-        if ix >= index.len() {
-            None
-        } else {
-            Some(IndexArrayEntry::decode_from(&index[ix..ix+2]))
+impl DenseIndex {
+    pub fn lookup(&self, buf: &[u8], ix: u32) -> Option<u32> {
+        let data = bytes_to_words(&buf[self.start..self.end]);
+        data.get(ix as usize).map(|d| u32::from_be(*d))
+    }
+    pub fn from_buf(buf: &[u8], start: usize, end: usize) -> Self {
+        assert!((end-start)%4 == 0 && start <= end && end <= buf.len());
+        DenseIndex {
+            start: start,
+            end: end
         }
     }
+}
 
-    fn item_from_pos(&self, positions: &[u32], pos: u32) -> u32 {
-        positions[pos as usize].to_be()
-    }
+pub fn write_dense_index(entries: Vec<u32>, buf: &mut Cursor<Vec<u8>>) {
+    let elen = entries.len();
+    assert!(elen < u32::MAX as usize);
 
-    #[inline(never)]
-    pub fn lookup_item(&self, buf: &[u8], node: NodeId) -> Option<u32> {
-        let index = bytes_to_words(&buf[self.index_start..self.index_end]);
-        let positions = bytes_to_words(&buf[self.position_start..self.index_start]);
-        let (x, s) = (node / 32 as u32, node % 32 as u32);
-        let result = match self.lookup_index(index, x) {
-            Some(IndexArrayEntry { bits, first_pos }) => {
-                let bit = 1<<s;
-                if bits & bit == 0 {
-                    None
-                } else {
-                    let prev_nodes_for_entry = (bits&(bit-1)).count_ones();
-                    Some(self.item_from_pos(
-                        positions,
-                        first_pos+prev_nodes_for_entry))
-                }
-            }
-            None => None // trailing zero
-        };
-        debug!("lookup_item({:?}) = {:?}", node, result);
-        result
+    for entry in entries {
+        write_be_u32(buf, entry);
     }
 
-    pub fn from_buf(buf: &[u8], start: usize, end: usize) -> Self {
-        let buf = bytes_to_words(&buf[start..end]);
-        let position_count = buf[0].to_be() as usize;
-        let position_len = position_count*4;
-        info!("loaded index - position: {}-{}-{}", start, start+position_len, end);
-        debug!("index contents are {:?}",
-               buf.iter().map(|b| format!("{:08x}", b)).collect::<Vec<_>>().concat());
-        assert!(end-4-start >= position_len);
-        assert_eq!((end-4-start-position_len)%8, 0);
-        Index {
-            position_start: start+4,
-            index_start: start+position_len+4,
-            index_end: end
-        }
-    }
+    info!("write_dense_index: {} entries", elen);
 }
 
 fn write_be_u32<W: Write>(w: &mut W, u: u32) {
@@ -162,47 +143,3 @@ fn bytes_to_words(b: &[u8]) -> &[u32] {
     assert!(b.len() % 4 == 0);
     unsafe { slice::from_raw_parts(b.as_ptr() as *const u32, b.len()/4) }
 }
-
-#[test]
-fn test_index() {
-    let entries = vec![
-        IndexEntry { node: 0, pos: 17 },
-        IndexEntry { node: 31, pos: 29 },
-        IndexEntry { node: 32, pos: 1175 },
-        IndexEntry { node: 191, pos: 21 },
-        IndexEntry { node: 128, pos: 34 },
-        IndexEntry { node: 145, pos: 70 },
-        IndexEntry { node: 305, pos: 93214 },
-        IndexEntry { node: 138, pos: 64 },
-        IndexEntry { node: 129, pos: 53 },
-        IndexEntry { node: 192, pos: 33334 },
-        IndexEntry { node: 200, pos: 80123 },
-    ];
-    let mut c = Cursor::new(vec![]);
-    write_index(entries.clone(), &mut c);
-    let mut buf = c.into_inner();
-    let expected: &[u8] = &[
-        0, 0, 0, 11, // # entries
-        // values:
-        0,0,0,17, 0,0,0,29, 0,0,4,151, 0,0,0,34,
-        0,0,0,53, 0,0,0,64, 0,0,0,70, 0,0,0,21,
-        0,0,130,54, 0,1,56,251, 0,1,108,30,
-        // index:
-        128,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,2,
-        0,0,0,0,0,0,0,3,   0,0,0,0,0,0,0,3,
-        0,2,4,3,0,0,0,3,   128,0,0,0,0,0,0,7,
-        0,0,1,1,0,0,0,8,   0,0,0,0,0,0,0,10,
-        0,0,0,0,0,0,0,10,  0,2,0,0,0,0,0,10
-    ];
-    assert_eq!(buf, expected);
-
-    // insert some junk padding
-    for i in 0..17 { buf.insert(0, i); buf.push(i) }
-    let index = Index::from_buf(&buf, 17, buf.len()-17);
-
-    // test round-trip
-    for i in 0..4096 {
-        assert_eq!(index.lookup_item(&buf, i),
-                   entries.iter().find(|e| e.node == i).map(|n| n.pos as u32));
-    }
-}
index 2f481f70aafe9b24ad363c1c4ec4d5f5c5049dd8..77092d0802fb37ee54e1abbde8b5f60598e840b2 100644 (file)
@@ -308,23 +308,28 @@ impl<'a> Context<'a> {
     }
 
     pub fn report_load_errs(&mut self) {
-        let message = if !self.rejected_via_hash.is_empty() {
-            format!("found possibly newer version of crate `{}`",
-                    self.ident)
+        let add = match self.root {
+            &None => String::new(),
+            &Some(ref r) => format!(" which `{}` depends on",
+                                    r.ident)
+        };
+        if !self.rejected_via_hash.is_empty() {
+            span_err!(self.sess, self.span, E0460,
+                      "found possibly newer version of crate `{}`{}",
+                      self.ident, add);
         } else if !self.rejected_via_triple.is_empty() {
-            format!("couldn't find crate `{}` with expected target triple {}",
-                    self.ident, self.triple)
+            span_err!(self.sess, self.span, E0461,
+                      "couldn't find crate `{}` with expected target triple {}{}",
+                      self.ident, self.triple, add);
         } else if !self.rejected_via_kind.is_empty() {
-            format!("found staticlib `{}` instead of rlib or dylib", self.ident)
+            span_err!(self.sess, self.span, E0462,
+                      "found staticlib `{}` instead of rlib or dylib{}",
+                      self.ident, add);
         } else {
-            format!("can't find crate for `{}`", self.ident)
-        };
-        let message = match self.root {
-            &None => message,
-            &Some(ref r) => format!("{} which `{}` depends on",
-                                    message, r.ident)
-        };
-        self.sess.span_err(self.span, &message[..]);
+            span_err!(self.sess, self.span, E0463,
+                      "can't find crate for `{}`{}",
+                      self.ident, add);
+        }
 
         if !self.rejected_via_triple.is_empty() {
             let mismatches = self.rejected_via_triple.iter();
@@ -473,9 +478,9 @@ impl<'a> Context<'a> {
             0 => None,
             1 => Some(libraries.into_iter().next().unwrap()),
             _ => {
-                self.sess.span_err(self.span,
-                    &format!("multiple matching crates for `{}`",
-                            self.crate_name));
+                span_err!(self.sess, self.span, E0464,
+                          "multiple matching crates for `{}`",
+                          self.crate_name);
                 self.sess.note("candidates:");
                 for lib in &libraries {
                     match lib.dylib {
@@ -543,11 +548,9 @@ impl<'a> Context<'a> {
                 }
             };
             if ret.is_some() {
-                self.sess.span_err(self.span,
-                                   &format!("multiple {} candidates for `{}` \
-                                            found",
-                                           flavor,
-                                           self.crate_name));
+                span_err!(self.sess, self.span, E0465,
+                          "multiple {} candidates for `{}` found",
+                          flavor, self.crate_name);
                 self.sess.span_note(self.span,
                                     &format!(r"candidate #1: {}",
                                             ret.as_ref().unwrap().0
@@ -723,7 +726,7 @@ fn get_metadata_section(target: &Target, filename: &Path)
         ret = Some(get_metadata_section_imp(target, filename));
     });
     info!("reading {:?} => {:?}", filename.file_name().unwrap(), dur);
-    return ret.unwrap();;
+    ret.unwrap()
 }
 
 fn get_metadata_section_imp(target: &Target, filename: &Path)
index 527f5919e2ddcd48fbe6058759e6979c0bf427a2..ca5999afbd3afc231256a08fd0d678842ccc3b6c 100644 (file)
@@ -21,7 +21,6 @@ use syntax::attr;
 use syntax::visit;
 use syntax::visit::Visitor;
 use syntax::attr::AttrMetaMethods;
-use rustc_front::attr::AttrMetaMethods as FrontAttrMetaMethods;
 
 struct MacroLoader<'a> {
     sess: &'a Session,
@@ -41,6 +40,10 @@ impl<'a> MacroLoader<'a> {
     }
 }
 
+pub fn call_bad_macro_reexport(a: &Session, b: Span) {
+    span_err!(a, b, E0467, "bad macro reexport");
+}
+
 /// Read exported macros.
 pub fn read_macro_defs(sess: &Session, krate: &ast::Crate) -> Vec<ast::MacroDef> {
     let mut loader = MacroLoader::new(sess);
@@ -91,7 +94,7 @@ impl<'a, 'v> Visitor<'v> for MacroLoader<'a> {
                             if let ast::MetaWord(ref name) = attr.node {
                                 sel.insert(name.clone(), attr.span);
                             } else {
-                                self.sess.span_err(attr.span, "bad macro import");
+                                span_err!(self.sess, attr.span, E0466, "bad macro import");
                             }
                         }
                     }
@@ -100,7 +103,7 @@ impl<'a, 'v> Visitor<'v> for MacroLoader<'a> {
                     let names = match attr.meta_item_list() {
                         Some(names) => names,
                         None => {
-                            self.sess.span_err(attr.span, "bad macro reexport");
+                            call_bad_macro_reexport(self.sess, attr.span);
                             continue;
                         }
                     };
@@ -109,7 +112,7 @@ impl<'a, 'v> Visitor<'v> for MacroLoader<'a> {
                         if let ast::MetaWord(ref name) = attr.node {
                             reexport.insert(name.clone(), attr.span);
                         } else {
-                            self.sess.span_err(attr.span, "bad macro reexport");
+                            call_bad_macro_reexport(self.sess, attr.span);
                         }
                     }
                 }
@@ -141,8 +144,8 @@ impl<'a> MacroLoader<'a> {
         }
 
         if !self.span_whitelist.contains(&vi.span) {
-            self.sess.span_err(vi.span, "an `extern crate` loading macros must be at \
-                                         the crate root");
+            span_err!(self.sess, vi.span, E0468,
+                      "an `extern crate` loading macros must be at the crate root");
             return;
         }
 
@@ -167,14 +170,16 @@ impl<'a> MacroLoader<'a> {
         if let Some(sel) = import.as_ref() {
             for (name, span) in sel {
                 if !seen.contains(&name) {
-                    self.sess.span_err(*span, "imported macro not found");
+                    span_err!(self.sess, *span, E0469,
+                              "imported macro not found");
                 }
             }
         }
 
         for (name, span) in &reexport {
             if !seen.contains(&name) {
-                self.sess.span_err(*span, "reexported macro not found");
+                span_err!(self.sess, *span, E0470,
+                          "reexported macro not found");
             }
         }
     }
index 7856890724cb65c7d01c1ca1e5be3a554f76b7d4..d03af6b672284b2accff9b886315e06aa71ad880 100644 (file)
 
 #![allow(non_camel_case_types)]
 
-pub use self::DefIdSource::*;
-
 use rustc_front::hir;
 
-use middle::def_id::DefId;
+use middle::def_id::{DefId, DefIndex};
 use middle::region;
 use middle::subst;
 use middle::subst::VecPerParamSpace;
@@ -36,32 +34,7 @@ use syntax::parse::token;
 // parse_from_str. Extra parameters are for converting to/from def_ids in the
 // data buffer. Whatever format you choose should not contain pipe characters.
 
-// Def id conversion: when we encounter def-ids, they have to be translated.
-// For example, the crate number must be converted from the crate number used
-// in the library we are reading from into the local crate numbers in use
-// here.  To perform this translation, the type decoder is supplied with a
-// conversion function of type `conv_did`.
-//
-// Sometimes, particularly when inlining, the correct translation of the
-// def-id will depend on where it originated from.  Therefore, the conversion
-// function is given an indicator of the source of the def-id.  See
-// astencode.rs for more information.
-#[derive(Copy, Clone, Debug)]
-pub enum DefIdSource {
-    // Identifies a struct, trait, enum, etc.
-    NominalType,
-
-    // Identifies a type alias (`type X = ...`).
-    TypeWithId,
-
-    // Identifies a region parameter (`fn foo<'X>() { ... }`).
-    RegionParameter,
-
-    // Identifies a closure
-    ClosureSource
-}
-
-pub type DefIdConvert<'a> = &'a mut FnMut(DefIdSource, DefId) -> DefId;
+pub type DefIdConvert<'a> = &'a mut FnMut(DefId) -> DefId;
 
 pub struct TyDecoder<'a, 'tcx: 'a> {
     data: &'a [u8],
@@ -125,6 +98,12 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
         return &self.data[start_pos..end_pos];
     }
 
+    fn parse_vuint(&mut self) -> usize {
+        let res = rbml::reader::vuint_at(self.data, self.pos).unwrap();
+        self.pos = res.next;
+        res.val
+    }
+
     fn parse_name(&mut self, last: char) -> ast::Name {
         fn is_last(b: char, c: char) -> bool { return c == b; }
         let bytes = self.scan(|a| is_last(last, a));
@@ -183,9 +162,9 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
                 ty::BrAnon(id)
             }
             '[' => {
-                let def = self.parse_def(RegionParameter);
-                let ident = token::str_to_ident(&self.parse_str(']'));
-                ty::BrNamed(def, ident.name)
+                let def = self.parse_def();
+                let name = token::intern(&self.parse_str(']'));
+                ty::BrNamed(def, name)
             }
             'f' => {
                 let id = self.parse_u32();
@@ -209,22 +188,17 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
             }
             'B' => {
                 assert_eq!(self.next(), '[');
-                // this is the wrong NodeId, but `param_id` is only accessed
-                // by the receiver-matching code in collect, which won't
-                // be going down this code path, and anyway I will kill it
-                // the moment wfcheck becomes the standard.
-                let node_id = self.parse_uint() as ast::NodeId;
-                assert_eq!(self.next(), '|');
+                let def_id = self.parse_def();
                 let space = self.parse_param_space();
                 assert_eq!(self.next(), '|');
                 let index = self.parse_u32();
                 assert_eq!(self.next(), '|');
-                let nm = token::str_to_ident(&self.parse_str(']'));
+                let name = token::intern(&self.parse_str(']'));
                 ty::ReEarlyBound(ty::EarlyBoundRegion {
-                    param_id: node_id,
+                    def_id: def_id,
                     space: space,
                     index: index,
-                    name: nm.name
+                    name: name
                 })
             }
             'f' => {
@@ -314,7 +288,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
     }
 
     pub fn parse_trait_ref(&mut self) -> ty::TraitRef<'tcx> {
-        let def = self.parse_def(NominalType);
+        let def = self.parse_def();
         let substs = self.tcx.mk_substs(self.parse_substs());
         ty::TraitRef {def_id: def, substs: substs}
     }
@@ -343,7 +317,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
             'c' => return tcx.types.char,
             't' => {
                 assert_eq!(self.next(), '[');
-                let did = self.parse_def(NominalType);
+                let did = self.parse_def();
                 let substs = self.parse_substs();
                 assert_eq!(self.next(), ']');
                 let def = self.tcx.lookup_adt_def(did);
@@ -390,7 +364,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
                 return tcx.mk_tup(params);
             }
             'F' => {
-                let def_id = self.parse_def(NominalType);
+                let def_id = self.parse_def();
                 return tcx.mk_fn(Some(def_id), tcx.mk_bare_fn(self.parse_bare_fn_ty()));
             }
             'G' => {
@@ -405,11 +379,8 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
                 // we return it (modulo closure types, see below). But if not, then we
                 // jump to offset 123 and read the type from there.
 
-                let pos = self.parse_hex();
-                assert_eq!(self.next(), ':');
-                let len = self.parse_hex();
-                assert_eq!(self.next(), '#');
-                let key = ty::CReaderCacheKey {cnum: self.krate, pos: pos, len: len };
+                let pos = self.parse_vuint();
+                let key = ty::CReaderCacheKey { cnum: self.krate, pos: pos };
                 match tcx.rcache.borrow().get(&key).cloned() {
                     Some(tt) => {
                         // If there is a closure buried in the type some where, then we
@@ -432,13 +403,13 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
                 return tt;
             }
             '\"' => {
-                let _ = self.parse_def(TypeWithId);
+                let _ = self.parse_def();
                 let inner = self.parse_ty();
                 inner
             }
             'a' => {
                 assert_eq!(self.next(), '[');
-                let did = self.parse_def(NominalType);
+                let did = self.parse_def();
                 let substs = self.parse_substs();
                 assert_eq!(self.next(), ']');
                 let def = self.tcx.lookup_adt_def(did);
@@ -446,7 +417,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
             }
             'k' => {
                 assert_eq!(self.next(), '[');
-                let did = self.parse_def(ClosureSource);
+                let did = self.parse_def();
                 let substs = self.parse_substs();
                 let mut tys = vec![];
                 while self.peek() != '.' {
@@ -481,9 +452,9 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
         ty::TypeAndMut { ty: self.parse_ty(), mutbl: m }
     }
 
-    fn parse_def(&mut self, source: DefIdSource) -> DefId {
+    fn parse_def(&mut self) -> DefId {
         let def_id = parse_defid(self.scan(|c| c == '|'));
-        return (self.conv_def_id)(source, def_id);
+        return (self.conv_def_id)(def_id);
     }
 
     fn parse_uint(&mut self) -> usize {
@@ -508,19 +479,6 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
         subst::ParamSpace::from_uint(self.parse_uint())
     }
 
-    fn parse_hex(&mut self) -> usize {
-        let mut n = 0;
-        loop {
-            let cur = self.peek();
-            if (cur < '0' || cur > '9') && (cur < 'a' || cur > 'f') { return n; }
-            self.pos = self.pos + 1;
-            n *= 16;
-            if '0' <= cur && cur <= '9' {
-                n += (cur as usize) - ('0' as usize);
-            } else { n += 10 + (cur as usize) - ('a' as usize); }
-        };
-    }
-
     fn parse_abi_set(&mut self) -> abi::Abi {
         assert_eq!(self.next(), '[');
         let bytes = self.scan(|c| c == ']');
@@ -586,7 +544,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
             'p' => ty::Binder(self.parse_projection_predicate()).to_predicate(),
             'w' => ty::Predicate::WellFormed(self.parse_ty()),
             'O' => {
-                let def_id = self.parse_def(NominalType);
+                let def_id = self.parse_def();
                 assert_eq!(self.next(), '|');
                 ty::Predicate::ObjectSafe(def_id)
             }
@@ -598,7 +556,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
         ty::ProjectionPredicate {
             projection_ty: ty::ProjectionTy {
                 trait_ref: self.parse_trait_ref(),
-                item_name: token::str_to_ident(&self.parse_str('|')).name,
+                item_name: token::intern(&self.parse_str('|')),
             },
             ty: self.parse_ty(),
         }
@@ -606,12 +564,12 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
 
     pub fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> {
         let name = self.parse_name(':');
-        let def_id = self.parse_def(NominalType);
+        let def_id = self.parse_def();
         let space = self.parse_param_space();
         assert_eq!(self.next(), '|');
         let index = self.parse_u32();
         assert_eq!(self.next(), '|');
-        let default_def_id = self.parse_def(NominalType);
+        let default_def_id = self.parse_def();
         let default = self.parse_opt(|this| this.parse_ty());
         let object_lifetime_default = self.parse_object_lifetime_default();
 
@@ -628,7 +586,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
 
     pub fn parse_region_param_def(&mut self) -> ty::RegionParameterDef {
         let name = self.parse_name(':');
-        let def_id = self.parse_def(NominalType);
+        let def_id = self.parse_def();
         let space = self.parse_param_space();
         assert_eq!(self.next(), '|');
         let index = self.parse_u32();
@@ -736,11 +694,12 @@ fn parse_defid(buf: &[u8]) -> DefId {
     let def_num = match str::from_utf8(def_part).ok().and_then(|s| {
         s.parse::<usize>().ok()
     }) {
-        Some(dn) => dn as ast::NodeId,
+        Some(dn) => dn,
         None => panic!("internal error: parse_defid: id expected, found {:?}",
                        def_part)
     };
-    DefId { krate: crate_num, node: def_num }
+    let index = DefIndex::new(def_num);
+    DefId { krate: crate_num, index: index }
 }
 
 fn parse_unsafety(c: char) -> hir::Unsafety {
index d7554c4cf750186b1aa619f037d1252f58ad328c..1b993a00e28448889342ca4fb373bb3f92dbd812 100644 (file)
@@ -14,6 +14,7 @@
 #![allow(non_camel_case_types)]
 
 use std::cell::RefCell;
+use std::io::Cursor;
 use std::io::prelude::*;
 
 use middle::def_id::DefId;
@@ -27,9 +28,10 @@ use util::nodemap::FnvHashMap;
 use rustc_front::hir;
 
 use syntax::abi::Abi;
+use syntax::ast;
 use syntax::diagnostic::SpanHandler;
 
-use rbml::writer::Encoder;
+use rbml::writer::{self, Encoder};
 
 macro_rules! mywrite { ($w:expr, $($arg:tt)*) => ({ write!($w.writer, $($arg)*); }) }
 
@@ -46,14 +48,14 @@ pub struct ctxt<'a, 'tcx: 'a> {
 // Extra parameters are for converting to/from def_ids in the string rep.
 // Whatever format you choose should not contain pipe characters.
 pub struct ty_abbrev {
-    s: String
+    s: Vec<u8>
 }
 
 pub type abbrev_map<'tcx> = RefCell<FnvHashMap<Ty<'tcx>, ty_abbrev>>;
 
 pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) {
     match cx.abbrevs.borrow_mut().get(&t) {
-        Some(a) => { w.writer.write_all(a.s.as_bytes()); return; }
+        Some(a) => { w.writer.write_all(&a.s); return; }
         None => {}
     }
 
@@ -65,26 +67,26 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) {
         ty::TyChar => mywrite!(w, "c"),
         ty::TyInt(t) => {
             match t {
-                hir::TyIs => mywrite!(w, "is"),
-                hir::TyI8 => mywrite!(w, "MB"),
-                hir::TyI16 => mywrite!(w, "MW"),
-                hir::TyI32 => mywrite!(w, "ML"),
-                hir::TyI64 => mywrite!(w, "MD")
+                ast::TyIs => mywrite!(w, "is"),
+                ast::TyI8 => mywrite!(w, "MB"),
+                ast::TyI16 => mywrite!(w, "MW"),
+                ast::TyI32 => mywrite!(w, "ML"),
+                ast::TyI64 => mywrite!(w, "MD")
             }
         }
         ty::TyUint(t) => {
             match t {
-                hir::TyUs => mywrite!(w, "us"),
-                hir::TyU8 => mywrite!(w, "Mb"),
-                hir::TyU16 => mywrite!(w, "Mw"),
-                hir::TyU32 => mywrite!(w, "Ml"),
-                hir::TyU64 => mywrite!(w, "Md")
+                ast::TyUs => mywrite!(w, "us"),
+                ast::TyU8 => mywrite!(w, "Mb"),
+                ast::TyU16 => mywrite!(w, "Mw"),
+                ast::TyU32 => mywrite!(w, "Ml"),
+                ast::TyU64 => mywrite!(w, "Md")
             }
         }
         ty::TyFloat(t) => {
             match t {
-                hir::TyF32 => mywrite!(w, "Mf"),
-                hir::TyF64 => mywrite!(w, "MF"),
+                ast::TyF32 => mywrite!(w, "Mf"),
+                ast::TyF64 => mywrite!(w, "MF"),
             }
         }
         ty::TyEnum(def, substs) => {
@@ -165,19 +167,22 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Encoder, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx>) {
 
     let end = w.mark_stable_position();
     let len = end - pos;
-    fn estimate_sz(u: u64) -> u64 {
-        let mut n = u;
-        let mut len = 0;
-        while n != 0 { len += 1; n = n >> 4; }
-        return len;
-    }
-    let abbrev_len = 3 + estimate_sz(pos) + estimate_sz(len);
-    if abbrev_len < len {
-        // I.e. it's actually an abbreviation.
-        cx.abbrevs.borrow_mut().insert(t, ty_abbrev {
-            s: format!("#{:x}:{:x}#", pos, len)
-        });
-    }
+
+    let buf: &mut [u8] = &mut [0; 16]; // vuint < 15 bytes
+    let mut abbrev = Cursor::new(buf);
+    abbrev.write_all(b"#");
+    writer::write_vuint(&mut abbrev, pos as usize);
+
+    cx.abbrevs.borrow_mut().insert(t, ty_abbrev {
+        s: if abbrev.position() < len {
+            abbrev.get_ref()[..abbrev.position() as usize].to_owned()
+        } else {
+            // if the abbreviation is longer than the real type,
+            // don't use #-notation. However, insert it here so
+            // other won't have to `mark_stable_position`
+            w.writer.get_ref()[pos as usize..end as usize].to_owned()
+        }
+    });
 }
 
 fn enc_mutability(w: &mut Encoder, mt: hir::Mutability) {
@@ -249,7 +254,7 @@ pub fn enc_region(w: &mut Encoder, cx: &ctxt, r: ty::Region) {
         }
         ty::ReEarlyBound(ref data) => {
             mywrite!(w, "B[{}|{}|{}|{}]",
-                     data.param_id,
+                     (cx.ds)(data.def_id),
                      data.space.to_uint(),
                      data.index,
                      data.name);
index 3b837277203972d0a789f9e8abd5e9ce540237e0..2bf749d93cec471c63cdc31b47dc39f4f74cc950 100644 (file)
@@ -60,6 +60,8 @@ pub fn prim_ty_to_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
     }
 }
 
+/// If a type in the AST is a primitive type, return the ty::Ty corresponding
+/// to it.
 pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
                                -> Option<Ty<'tcx>> {
     if let ast::TyPath(None, ref path) = ast_ty.node {
index 0bd4434857abd50ca1d6d989b05ad0d8c449e6fa..e81445f19ede661ff85aadda7ee947415bf41ce7 100644 (file)
@@ -24,21 +24,19 @@ use metadata::decoder;
 use metadata::encoder as e;
 use metadata::inline::{InlinedItem, InlinedItemRef};
 use metadata::tydecode;
-use metadata::tydecode::{DefIdSource, NominalType, TypeWithId};
-use metadata::tydecode::{RegionParameter, ClosureSource};
 use metadata::tyencode;
 use middle::ty::adjustment;
 use middle::ty::cast;
 use middle::check_const::ConstQualif;
 use middle::def;
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::DefId;
 use middle::privacy::{AllPublic, LastMod};
 use middle::region;
 use middle::subst;
-use middle::subst::VecPerParamSpace;
 use middle::ty::{self, Ty};
 
 use syntax::{ast, ast_util, codemap};
+use syntax::ast::NodeIdAssigner;
 use syntax::codemap::Span;
 use syntax::ptr::P;
 
@@ -56,8 +54,9 @@ use serialize::EncoderHelpers;
 
 #[cfg(test)] use std::io::Cursor;
 #[cfg(test)] use syntax::parse;
+#[cfg(test)] use syntax::ast::NodeId;
 #[cfg(test)] use rustc_front::print::pprust;
-#[cfg(test)] use rustc_front::lowering::lower_item;
+#[cfg(test)] use rustc_front::lowering::{lower_item, LoweringContext};
 
 struct DecodeContext<'a, 'b, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
@@ -72,10 +71,6 @@ trait tr {
     fn tr(&self, dcx: &DecodeContext) -> Self;
 }
 
-trait tr_intern {
-    fn tr_intern(&self, dcx: &DecodeContext) -> DefId;
-}
-
 // ______________________________________________________________________
 // Top-level methods.
 
@@ -129,10 +124,13 @@ impl<'a, 'b, 'c, 'tcx> ast_map::FoldOps for &'a DecodeContext<'b, 'c, 'tcx> {
 pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
                                  tcx: &ty::ctxt<'tcx>,
                                  path: Vec<ast_map::PathElem>,
-                                 par_doc: rbml::Doc)
-                                 -> Result<&'tcx InlinedItem, Vec<ast_map::PathElem>> {
+                                 def_path: ast_map::DefPath,
+                                 par_doc: rbml::Doc,
+                                 orig_did: DefId)
+                                 -> Result<&'tcx InlinedItem, (Vec<ast_map::PathElem>,
+                                                               ast_map::DefPath)> {
     match par_doc.opt_child(c::tag_ast) {
-      None => Err(path),
+      None => Err((path, def_path)),
       Some(ast_doc) => {
         let mut path_as_str = None;
         debug!("> Decoding inlined fn: {:?}::?",
@@ -153,20 +151,21 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata,
             last_filemap_index: Cell::new(0)
         };
         let raw_ii = decode_ast(ast_doc);
-        let ii = ast_map::map_decoded_item(&dcx.tcx.map, path, raw_ii, dcx);
+        let ii = ast_map::map_decoded_item(&dcx.tcx.map, path, def_path, raw_ii, dcx);
 
-        let ident = match *ii {
-            InlinedItem::Item(ref i) => i.ident,
-            InlinedItem::Foreign(ref i) => i.ident,
-            InlinedItem::TraitItem(_, ref ti) => ti.ident,
-            InlinedItem::ImplItem(_, ref ii) => ii.ident
+        let name = match *ii {
+            InlinedItem::Item(ref i) => i.name,
+            InlinedItem::Foreign(ref i) => i.name,
+            InlinedItem::TraitItem(_, ref ti) => ti.name,
+            InlinedItem::ImplItem(_, ref ii) => ii.name
         };
-        debug!("Fn named: {}", ident);
+        debug!("Fn named: {}", name);
         debug!("< Decoded inlined fn: {}::{}",
                path_as_str.unwrap(),
-               ident);
+               name);
         region::resolve_inlined_item(&tcx.sess, &tcx.region_maps, ii);
         decode_side_tables(dcx, ast_doc);
+        copy_item_types(dcx, ii, orig_did);
         match *ii {
           InlinedItem::Item(ref i) => {
             debug!(">>> DECODED ITEM >>>\n{}\n<<< DECODED ITEM <<<",
@@ -213,24 +212,10 @@ impl<'a, 'b, 'tcx> DecodeContext<'a, 'b, 'tcx> {
     /// be inlined.  Note that even when the inlined function is referencing itself recursively, we
     /// would want `tr_def_id` for that reference--- conceptually the function calls the original,
     /// non-inlined version, and trans deals with linking that recursive call to the inlined copy.
-    ///
-    /// However, there are a *few* cases where def-ids are used but we know that the thing being
-    /// referenced is in fact *internal* to the item being inlined.  In those cases, you should use
-    /// `tr_intern_def_id()` below.
     pub fn tr_def_id(&self, did: DefId) -> DefId {
-
         decoder::translate_def_id(self.cdata, did)
     }
 
-    /// Translates an INTERNAL def-id, meaning a def-id that is
-    /// known to refer to some part of the item currently being
-    /// inlined.  In that case, we want to convert the def-id to
-    /// refer to the current crate and to the new, inlined node-id.
-    pub fn tr_intern_def_id(&self, did: DefId) -> DefId {
-        assert_eq!(did.krate, LOCAL_CRATE);
-        DefId { krate: LOCAL_CRATE, node: self.tr_id(did.node) }
-    }
-
     /// Translates a `Span` from an extern crate to the corresponding `Span`
     /// within the local crate's codemap. `creader::import_codemap()` will
     /// already have allocated any additionally needed FileMaps in the local
@@ -289,12 +274,6 @@ impl<'a, 'b, 'tcx> DecodeContext<'a, 'b, 'tcx> {
     }
 }
 
-impl tr_intern for DefId {
-    fn tr_intern(&self, dcx: &DecodeContext) -> DefId {
-        dcx.tr_intern_def_id(*self)
-    }
-}
-
 impl tr for DefId {
     fn tr(&self, dcx: &DecodeContext) -> DefId {
         dcx.tr_def_id(*self)
@@ -460,7 +439,11 @@ impl tr for def::Def {
           def::DefStatic(did, m) => { def::DefStatic(did.tr(dcx), m) }
           def::DefConst(did) => { def::DefConst(did.tr(dcx)) }
           def::DefAssociatedConst(did) => def::DefAssociatedConst(did.tr(dcx)),
-          def::DefLocal(nid) => { def::DefLocal(dcx.tr_id(nid)) }
+          def::DefLocal(_, nid) => {
+              let nid = dcx.tr_id(nid);
+              let did = dcx.tcx.map.local_def_id(nid);
+              def::DefLocal(did, nid)
+          }
           def::DefVariant(e_did, v_did, is_s) => {
             def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s)
           },
@@ -471,11 +454,13 @@ impl tr for def::Def {
           def::DefPrimTy(p) => def::DefPrimTy(p),
           def::DefTyParam(s, index, def_id, n) => def::DefTyParam(s, index, def_id.tr(dcx), n),
           def::DefUse(did) => def::DefUse(did.tr(dcx)),
-          def::DefUpvar(nid1, index, nid2) => {
-            def::DefUpvar(dcx.tr_id(nid1), index, dcx.tr_id(nid2))
+          def::DefUpvar(_, nid1, index, nid2) => {
+              let nid1 = dcx.tr_id(nid1);
+              let nid2 = dcx.tr_id(nid2);
+              let did1 = dcx.tcx.map.local_def_id(nid1);
+              def::DefUpvar(did1, nid1, index, nid2)
           }
           def::DefStruct(did) => def::DefStruct(did.tr(dcx)),
-          def::DefRegion(nid) => def::DefRegion(dcx.tr_id(nid)),
           def::DefLabel(nid) => def::DefLabel(dcx.tr_id(nid))
         }
     }
@@ -568,44 +553,10 @@ impl<'a, 'tcx> read_method_callee_helper<'tcx> for reader::Decoder<'a> {
     }
 }
 
-pub fn encode_closure_kind(ebml_w: &mut Encoder, kind: ty::ClosureKind) {
-    kind.encode(ebml_w).unwrap();
-}
-
 pub fn encode_cast_kind(ebml_w: &mut Encoder, kind: cast::CastKind) {
     kind.encode(ebml_w).unwrap();
 }
 
-pub trait vtable_decoder_helpers<'tcx> {
-    fn read_vec_per_param_space<T, F>(&mut self, f: F) -> VecPerParamSpace<T> where
-        F: FnMut(&mut Self) -> T;
-}
-
-impl<'tcx, 'a> vtable_decoder_helpers<'tcx> for reader::Decoder<'a> {
-    fn read_vec_per_param_space<T, F>(&mut self, mut f: F) -> VecPerParamSpace<T> where
-        F: FnMut(&mut reader::Decoder<'a>) -> T,
-    {
-        let types = self.read_to_vec(|this| Ok(f(this))).unwrap();
-        let selfs = self.read_to_vec(|this| Ok(f(this))).unwrap();
-        let fns = self.read_to_vec(|this| Ok(f(this))).unwrap();
-        VecPerParamSpace::new(types, selfs, fns)
-    }
-}
-
-// ___________________________________________________________________________
-//
-
-fn encode_vec_per_param_space<T, F>(rbml_w: &mut Encoder,
-                                    v: &subst::VecPerParamSpace<T>,
-                                    mut f: F) where
-    F: FnMut(&mut Encoder, &T),
-{
-    for &space in &subst::ParamSpace::all() {
-        rbml_w.emit_from_vec(v.get_slice(space),
-                             |rbml_w, n| Ok(f(rbml_w, n))).unwrap();
-    }
-}
-
 // ______________________________________________________________________
 // Encoding and decoding the side tables
 
@@ -625,21 +576,13 @@ impl<'a, 'tcx> get_ty_str_ctxt<'tcx> for e::EncodeContext<'a, 'tcx> {
 }
 
 trait rbml_writer_helpers<'tcx> {
-    fn emit_closure_type<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
-                             closure_type: &ty::ClosureTy<'tcx>);
     fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region);
     fn emit_ty<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, ty: Ty<'tcx>);
     fn emit_tys<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>, tys: &[Ty<'tcx>]);
-    fn emit_type_param_def<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
-                               type_param_def: &ty::TypeParameterDef<'tcx>);
-    fn emit_region_param_def(&mut self, ecx: &e::EncodeContext,
-                             region_param_def: &ty::RegionParameterDef);
     fn emit_predicate<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
                           predicate: &ty::Predicate<'tcx>);
     fn emit_trait_ref<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
                           ty: &ty::TraitRef<'tcx>);
-    fn emit_type_scheme<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
-                            type_scheme: ty::TypeScheme<'tcx>);
     fn emit_substs<'a>(&mut self, ecx: &e::EncodeContext<'a, 'tcx>,
                        substs: &subst::Substs<'tcx>);
     fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
@@ -655,14 +598,6 @@ trait rbml_writer_helpers<'tcx> {
 }
 
 impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
-    fn emit_closure_type<'b>(&mut self,
-                             ecx: &e::EncodeContext<'b, 'tcx>,
-                             closure_type: &ty::ClosureTy<'tcx>) {
-        self.emit_opaque(|this| {
-            Ok(e::write_closure_type(ecx, this, closure_type))
-        });
-    }
-
     fn emit_region(&mut self, ecx: &e::EncodeContext, r: ty::Region) {
         self.emit_opaque(|this| Ok(e::write_region(ecx, this, r)));
     }
@@ -680,22 +615,6 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
         self.emit_opaque(|this| Ok(e::write_trait_ref(ecx, this, trait_ref)));
     }
 
-    fn emit_type_param_def<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
-                               type_param_def: &ty::TypeParameterDef<'tcx>) {
-        self.emit_opaque(|this| {
-            Ok(tyencode::enc_type_param_def(this,
-                                         &ecx.ty_str_ctxt(),
-                                         type_param_def))
-        });
-    }
-    fn emit_region_param_def(&mut self, ecx: &e::EncodeContext,
-                             region_param_def: &ty::RegionParameterDef) {
-        self.emit_opaque(|this| {
-            Ok(tyencode::enc_region_param_def(this,
-                                              &ecx.ty_str_ctxt(),
-                                              region_param_def))
-        });
-    }
     fn emit_predicate<'b>(&mut self, ecx: &e::EncodeContext<'b, 'tcx>,
                           predicate: &ty::Predicate<'tcx>) {
         self.emit_opaque(|this| {
@@ -705,32 +624,6 @@ impl<'a, 'tcx> rbml_writer_helpers<'tcx> for Encoder<'a> {
         });
     }
 
-    fn emit_type_scheme<'b>(&mut self,
-                            ecx: &e::EncodeContext<'b, 'tcx>,
-                            type_scheme: ty::TypeScheme<'tcx>) {
-        use serialize::Encoder;
-
-        self.emit_struct("TypeScheme", 2, |this| {
-            this.emit_struct_field("generics", 0, |this| {
-                this.emit_struct("Generics", 2, |this| {
-                    this.emit_struct_field("types", 0, |this| {
-                        Ok(encode_vec_per_param_space(
-                            this, &type_scheme.generics.types,
-                            |this, def| this.emit_type_param_def(ecx, def)))
-                    });
-                    this.emit_struct_field("regions", 1, |this| {
-                        Ok(encode_vec_per_param_space(
-                            this, &type_scheme.generics.regions,
-                            |this, def| this.emit_region_param_def(ecx, def)))
-                    })
-                })
-            });
-            this.emit_struct_field("ty", 1, |this| {
-                Ok(this.emit_ty(ecx, type_scheme.ty))
-            })
-        });
-    }
-
     fn emit_existential_bounds<'b>(&mut self, ecx: &e::EncodeContext<'b,'tcx>,
                                    bounds: &ty::ExistentialBounds<'tcx>) {
         self.emit_opaque(|this| Ok(tyencode::enc_existential_bounds(this,
@@ -933,7 +826,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
             rbml_w.tag(c::tag_table_upvar_capture_map, |rbml_w| {
                 rbml_w.id(id);
 
-                let var_id = freevar.def.def_id().node;
+                let var_id = freevar.def.var_id();
                 let upvar_id = ty::UpvarId {
                     var_id: var_id,
                     closure_expr_id: id
@@ -950,21 +843,6 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         }
     }
 
-    let lid = DefId { krate: LOCAL_CRATE, node: id };
-    if let Some(type_scheme) = tcx.tcache.borrow().get(&lid) {
-        rbml_w.tag(c::tag_table_tcache, |rbml_w| {
-            rbml_w.id(id);
-            rbml_w.emit_type_scheme(ecx, type_scheme.clone());
-        })
-    }
-
-    if let Some(type_param_def) = tcx.ty_param_defs.borrow().get(&id) {
-        rbml_w.tag(c::tag_table_param_defs, |rbml_w| {
-            rbml_w.id(id);
-            rbml_w.emit_type_param_def(ecx, type_param_def)
-        })
-    }
-
     let method_call = ty::MethodCall::expr(id);
     if let Some(method) = tcx.tables.borrow().method_map.get(&method_call) {
         rbml_w.tag(c::tag_table_method_map, |rbml_w| {
@@ -996,20 +874,6 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         })
     }
 
-    if let Some(closure_type) = tcx.tables.borrow().closure_tys.get(&DefId::local(id)) {
-        rbml_w.tag(c::tag_table_closure_tys, |rbml_w| {
-            rbml_w.id(id);
-            rbml_w.emit_closure_type(ecx, closure_type);
-        })
-    }
-
-    if let Some(closure_kind) = tcx.tables.borrow().closure_kinds.get(&DefId::local(id)) {
-        rbml_w.tag(c::tag_table_closure_kinds, |rbml_w| {
-            rbml_w.id(id);
-            encode_closure_kind(rbml_w, *closure_kind)
-        })
-    }
-
     if let Some(cast_kind) = tcx.cast_kinds.borrow().get(&id) {
         rbml_w.tag(c::tag_table_cast_kinds, |rbml_w| {
             rbml_w.id(id);
@@ -1049,14 +913,8 @@ trait rbml_decoder_decoder_helpers<'tcx> {
                               -> ty::TraitRef<'tcx>;
     fn read_poly_trait_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
                                    -> ty::PolyTraitRef<'tcx>;
-    fn read_type_param_def<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-                                   -> ty::TypeParameterDef<'tcx>;
-    fn read_region_param_def(&mut self, dcx: &DecodeContext)
-                             -> ty::RegionParameterDef;
     fn read_predicate<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
                               -> ty::Predicate<'tcx>;
-    fn read_type_scheme<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-                                -> ty::TypeScheme<'tcx>;
     fn read_existential_bounds<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
                                        -> ty::ExistentialBounds<'tcx>;
     fn read_substs<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
@@ -1067,17 +925,12 @@ trait rbml_decoder_decoder_helpers<'tcx> {
                                     -> adjustment::AutoAdjustment<'tcx>;
     fn read_cast_kind<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
                                  -> cast::CastKind;
-    fn read_closure_kind<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-                                 -> ty::ClosureKind;
-    fn read_closure_ty<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-                               -> ty::ClosureTy<'tcx>;
     fn read_auto_deref_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
                                    -> adjustment::AutoDerefRef<'tcx>;
     fn read_autoref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
                             -> adjustment::AutoRef<'tcx>;
     fn convert_def_id(&mut self,
                       dcx: &DecodeContext,
-                      source: DefIdSource,
                       did: DefId)
                       -> DefId;
 
@@ -1101,7 +954,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
         self.read_opaque(|_, doc| {
             Ok(
                 tydecode::TyDecoder::with_doc(tcx, cdata.cnum, doc,
-                                              &mut |_, id| decoder::translate_def_id(cdata, id))
+                                              &mut |id| decoder::translate_def_id(cdata, id))
                     .parse_ty())
         }).unwrap()
     }
@@ -1123,7 +976,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
         self.read_opaque(|_, doc| {
             Ok(
                 tydecode::TyDecoder::with_doc(tcx, cdata.cnum, doc,
-                                              &mut |_, id| decoder::translate_def_id(cdata, id))
+                                              &mut |id| decoder::translate_def_id(cdata, id))
                     .parse_substs())
         }).unwrap()
     }
@@ -1136,7 +989,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
             Ok(op(
                 &mut tydecode::TyDecoder::with_doc(
                     dcx.tcx, dcx.cdata.cnum, doc,
-                    &mut |s, a| this.convert_def_id(dcx, s, a))))
+                    &mut |a| this.convert_def_id(dcx, a))))
         }).unwrap();
 
         fn type_string(doc: rbml::Doc) -> String {
@@ -1173,48 +1026,12 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
         ty::Binder(self.read_ty_encoded(dcx, |decoder| decoder.parse_trait_ref()))
     }
 
-    fn read_type_param_def<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-                                   -> ty::TypeParameterDef<'tcx> {
-        self.read_ty_encoded(dcx, |decoder| decoder.parse_type_param_def())
-    }
-    fn read_region_param_def(&mut self, dcx: &DecodeContext)
-                             -> ty::RegionParameterDef {
-        self.read_ty_encoded(dcx, |decoder| decoder.parse_region_param_def())
-    }
     fn read_predicate<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
                               -> ty::Predicate<'tcx>
     {
         self.read_ty_encoded(dcx, |decoder| decoder.parse_predicate())
     }
 
-    fn read_type_scheme<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-                                -> ty::TypeScheme<'tcx> {
-        self.read_struct("TypeScheme", 3, |this| {
-            Ok(ty::TypeScheme {
-                generics: this.read_struct_field("generics", 0, |this| {
-                    this.read_struct("Generics", 2, |this| {
-                        Ok(ty::Generics {
-                            types:
-                            this.read_struct_field("types", 0, |this| {
-                                Ok(this.read_vec_per_param_space(
-                                    |this| this.read_type_param_def(dcx)))
-                            }).unwrap(),
-
-                            regions:
-                            this.read_struct_field("regions", 1, |this| {
-                                Ok(this.read_vec_per_param_space(
-                                    |this| this.read_region_param_def(dcx)))
-                            }).unwrap(),
-                        })
-                    })
-                }).unwrap(),
-                ty: this.read_struct_field("ty", 1, |this| {
-                    Ok(this.read_ty(dcx))
-                }).unwrap()
-            })
-        }).unwrap()
-    }
-
     fn read_existential_bounds<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
                                        -> ty::ExistentialBounds<'tcx>
     {
@@ -1225,7 +1042,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
                            -> subst::Substs<'tcx> {
         self.read_opaque(|this, doc| {
             Ok(tydecode::TyDecoder::with_doc(dcx.tcx, dcx.cdata.cnum, doc,
-                                             &mut |s, a| this.convert_def_id(dcx, s, a))
+                                             &mut |a| this.convert_def_id(dcx, a))
                .parse_substs())
         }).unwrap()
     }
@@ -1332,18 +1149,6 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
         Decodable::decode(self).unwrap()
     }
 
-    fn read_closure_kind<'b, 'c>(&mut self, _dcx: &DecodeContext<'b, 'c, 'tcx>)
-                                 -> ty::ClosureKind
-    {
-        Decodable::decode(self).unwrap()
-    }
-
-    fn read_closure_ty<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
-                               -> ty::ClosureTy<'tcx>
-    {
-        self.read_ty_encoded(dcx, |decoder| decoder.parse_closure_ty())
-    }
-
     /// Converts a def-id that appears in a type.  The correct
     /// translation will depend on what kind of def-id this is.
     /// This is a subtle point: type definitions are not
@@ -1378,14 +1183,10 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
     /// def-ids so that all these distinctions were unnecessary.
     fn convert_def_id(&mut self,
                       dcx: &DecodeContext,
-                      source: tydecode::DefIdSource,
                       did: DefId)
                       -> DefId {
-        let r = match source {
-            NominalType | TypeWithId | RegionParameter => dcx.tr_def_id(did),
-            ClosureSource => dcx.tr_intern_def_id(did)
-        };
-        debug!("convert_def_id(source={:?}, did={:?})={:?}", source, did, r);
+        let r = dcx.tr_def_id(did);
+        debug!("convert_def_id(did={:?})={:?}", did, r);
         return r;
     }
 }
@@ -1450,15 +1251,6 @@ fn decode_side_tables(dcx: &DecodeContext,
                         let ub = val_dsr.read_upvar_capture(dcx);
                         dcx.tcx.tables.borrow_mut().upvar_capture_map.insert(upvar_id, ub);
                     }
-                    c::tag_table_tcache => {
-                        let type_scheme = val_dsr.read_type_scheme(dcx);
-                        let lid = DefId { krate: LOCAL_CRATE, node: id };
-                        dcx.tcx.register_item_type(lid, type_scheme);
-                    }
-                    c::tag_table_param_defs => {
-                        let bounds = val_dsr.read_type_param_def(dcx);
-                        dcx.tcx.ty_param_defs.borrow_mut().insert(id, bounds);
-                    }
                     c::tag_table_method_map => {
                         let (autoderef, method) = val_dsr.read_method_callee(dcx);
                         let method_call = ty::MethodCall {
@@ -1472,18 +1264,6 @@ fn decode_side_tables(dcx: &DecodeContext,
                             val_dsr.read_auto_adjustment(dcx);
                         dcx.tcx.tables.borrow_mut().adjustments.insert(id, adj);
                     }
-                    c::tag_table_closure_tys => {
-                        let closure_ty =
-                            val_dsr.read_closure_ty(dcx);
-                        dcx.tcx.tables.borrow_mut().closure_tys.insert(DefId::local(id),
-                                                                closure_ty);
-                    }
-                    c::tag_table_closure_kinds => {
-                        let closure_kind =
-                            val_dsr.read_closure_kind(dcx);
-                        dcx.tcx.tables.borrow_mut().closure_kinds.insert(DefId::local(id),
-                                                                  closure_kind);
-                    }
                     c::tag_table_cast_kinds => {
                         let cast_kind =
                             val_dsr.read_cast_kind(dcx);
@@ -1506,6 +1286,53 @@ fn decode_side_tables(dcx: &DecodeContext,
     }
 }
 
+// copy the tcache entries from the original item to the new
+// inlined item
+fn copy_item_types(dcx: &DecodeContext, ii: &InlinedItem, orig_did: DefId) {
+    fn copy_item_type(dcx: &DecodeContext,
+                      inlined_id: ast::NodeId,
+                      remote_did: DefId) {
+        let inlined_did = dcx.tcx.map.local_def_id(inlined_id);
+        dcx.tcx.register_item_type(inlined_did,
+                                   dcx.tcx.lookup_item_type(remote_did));
+
+    }
+    // copy the entry for the item itself
+    let item_node_id = match ii {
+        &InlinedItem::Item(ref i) => i.id,
+        &InlinedItem::TraitItem(_, ref ti) => ti.id,
+        &InlinedItem::ImplItem(_, ref ii) => ii.id,
+        &InlinedItem::Foreign(ref fi) => fi.id
+    };
+    copy_item_type(dcx, item_node_id, orig_did);
+
+    // copy the entries of inner items
+    if let &InlinedItem::Item(ref item) = ii {
+        match item.node {
+            hir::ItemEnum(ref def, _) => {
+                let orig_def = dcx.tcx.lookup_adt_def(orig_did);
+                for (i_variant, orig_variant) in
+                    def.variants.iter().zip(orig_def.variants.iter())
+                {
+                    debug!("astencode: copying variant {:?} => {:?}",
+                           orig_variant.did, i_variant.node.data.id());
+                    copy_item_type(dcx, i_variant.node.data.id(), orig_variant.did);
+                }
+            }
+            hir::ItemStruct(ref def, _) => {
+                if !def.is_struct() {
+                    let ctor_did = dcx.tcx.lookup_adt_def(orig_did)
+                        .struct_variant().did;
+                    debug!("astencode: copying ctor {:?} => {:?}", ctor_did,
+                           def.id());
+                    copy_item_type(dcx, def.id(), ctor_did);
+                }
+            }
+            _ => {}
+        }
+    }
+}
+
 // ______________________________________________________________________
 // Testing of astencode_gen
 
@@ -1551,6 +1378,22 @@ impl FakeExtCtxt for parse::ParseSess {
     fn parse_sess(&self) -> &parse::ParseSess { self }
 }
 
+#[cfg(test)]
+struct FakeNodeIdAssigner;
+
+#[cfg(test)]
+// It should go without saying that this may give unexpected results. Avoid
+// lowering anything which needs new nodes.
+impl NodeIdAssigner for FakeNodeIdAssigner {
+    fn next_node_id(&self) -> NodeId {
+        0
+    }
+
+    fn peek_node_id(&self) -> NodeId {
+        0
+    }
+}
+
 #[cfg(test)]
 fn mk_ctxt() -> parse::ParseSess {
     parse::ParseSess::new()
@@ -1569,7 +1412,9 @@ fn roundtrip(in_item: P<hir::Item>) {
 #[test]
 fn test_basic() {
     let cx = mk_ctxt();
-    roundtrip(lower_item(&quote_item!(&cx,
+    let fnia = FakeNodeIdAssigner;
+    let lcx = LoweringContext::new(&fnia, None);
+    roundtrip(lower_item(&lcx, &quote_item!(&cx,
         fn foo() {}
     ).unwrap()));
 }
@@ -1577,7 +1422,9 @@ fn test_basic() {
 #[test]
 fn test_smalltalk() {
     let cx = mk_ctxt();
-    roundtrip(lower_item(&quote_item!(&cx,
+    let fnia = FakeNodeIdAssigner;
+    let lcx = LoweringContext::new(&fnia, None);
+    roundtrip(lower_item(&lcx, &quote_item!(&cx,
         fn foo() -> isize { 3 + 4 } // first smalltalk program ever executed.
     ).unwrap()));
 }
@@ -1585,7 +1432,9 @@ fn test_smalltalk() {
 #[test]
 fn test_more() {
     let cx = mk_ctxt();
-    roundtrip(lower_item(&quote_item!(&cx,
+    let fnia = FakeNodeIdAssigner;
+    let lcx = LoweringContext::new(&fnia, None);
+    roundtrip(lower_item(&lcx, &quote_item!(&cx,
         fn foo(x: usize, y: usize) -> usize {
             let z = x + y;
             return z;
@@ -1602,10 +1451,12 @@ fn test_simplification() {
             return alist {eq_fn: eq_int, data: Vec::new()};
         }
     ).unwrap();
-    let hir_item = lower_item(&item);
+    let fnia = FakeNodeIdAssigner;
+    let lcx = LoweringContext::new(&fnia, None);
+    let hir_item = lower_item(&lcx, &item);
     let item_in = InlinedItemRef::Item(&hir_item);
     let item_out = simplify_ast(item_in);
-    let item_exp = InlinedItem::Item(lower_item(&quote_item!(&cx,
+    let item_exp = InlinedItem::Item(lower_item(&lcx, &quote_item!(&cx,
         fn new_int_alist<B>() -> alist<isize, B> {
             return alist {eq_fn: eq_int, data: Vec::new()};
         }
index 3f6385ad82cc4f9d0c845a934d3c2cc1cf866cd8..3b04dc3fb9b1a91399919b2c20918a6c736f3574 100644 (file)
@@ -284,7 +284,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
             }
 
             hir::ExprBreak(label) => {
-                let loop_scope = self.find_scope(expr, label.map(|l| l.node));
+                let loop_scope = self.find_scope(expr, label.map(|l| l.node.name));
                 let b = self.add_ast_node(expr.id, &[pred]);
                 self.add_exiting_edge(expr, b,
                                       loop_scope, loop_scope.break_index);
@@ -292,7 +292,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
             }
 
             hir::ExprAgain(label) => {
-                let loop_scope = self.find_scope(expr, label.map(|l| l.node));
+                let loop_scope = self.find_scope(expr, label.map(|l| l.node.name));
                 let a = self.add_ast_node(expr.id, &[pred]);
                 self.add_exiting_edge(expr, a,
                                       loop_scope, loop_scope.continue_index);
@@ -344,17 +344,15 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                 self.straightline(expr, pred, [r, l].iter().map(|&e| &**e))
             }
 
-            hir::ExprBox(Some(ref l), ref r) |
             hir::ExprIndex(ref l, ref r) |
             hir::ExprBinary(_, ref l, ref r) => { // NB: && and || handled earlier
                 self.straightline(expr, pred, [l, r].iter().map(|&e| &**e))
             }
 
-            hir::ExprBox(None, ref e) |
+            hir::ExprBox(ref e) |
             hir::ExprAddrOf(_, ref e) |
             hir::ExprCast(ref e, _) |
             hir::ExprUnary(_, ref e) |
-            hir::ExprParen(ref e) |
             hir::ExprField(ref e, _) |
             hir::ExprTupField(ref e, _) => {
                 self.straightline(expr, pred, Some(&**e).into_iter())
@@ -587,7 +585,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
 
     fn find_scope(&self,
                   expr: &hir::Expr,
-                  label: Option<ast::Ident>) -> LoopScope {
+                  label: Option<ast::Name>) -> LoopScope {
         if label.is_none() {
             return *self.loop_scopes.last().unwrap();
         }
index 661299cd7f3fc0aec502bee21c5ae89e2a0331f9..263c9bd15774d7a91ab63876838ffe5b56b74a9f 100644 (file)
@@ -39,6 +39,7 @@ use util::nodemap::NodeMap;
 use rustc_front::hir;
 use syntax::ast;
 use syntax::codemap::Span;
+use syntax::feature_gate::UnstableFeatures;
 use rustc_front::visit::{self, FnKind, Visitor};
 
 use std::collections::hash_map::Entry;
@@ -175,6 +176,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
         if mode == Mode::ConstFn {
             for arg in &fd.inputs {
                 match arg.pat.node {
+                    hir::PatWild(_) => {}
                     hir::PatIdent(hir::BindByValue(hir::MutImmutable), _, None) => {}
                     _ => {
                         span_err!(self.tcx.sess, arg.pat.span, E0022,
@@ -471,12 +473,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
                     ty::TyUint(_) | ty::TyInt(_) if div_or_rem => {
                         if !self.qualif.intersects(ConstQualif::NOT_CONST) {
                             match const_eval::eval_const_expr_partial(
-                                    self.tcx, ex, ExprTypeChecked) {
+                                    self.tcx, ex, ExprTypeChecked, None) {
                                 Ok(_) => {}
                                 Err(msg) => {
-                                    span_err!(self.tcx.sess, msg.span, E0020,
-                                              "{} in a constant expression",
-                                              msg.description())
+                                    self.tcx.sess.add_lint(::lint::builtin::CONST_ERR, ex.id,
+                                                           msg.span,
+                                                           msg.description().into_owned())
                                 }
                             }
                         }
@@ -499,9 +501,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
                 if self.qualif.intersects(ConstQualif::MUTABLE_MEM) && tc.interior_unsafe() {
                     outer = outer | ConstQualif::NOT_CONST;
                     if self.mode != Mode::Var {
-                        self.tcx.sess.span_err(ex.span,
-                            "cannot borrow a constant which contains \
-                             interior mutability, create a static instead");
+                        span_err!(self.tcx.sess, ex.span, E0492,
+                                  "cannot borrow a constant which contains \
+                                   interior mutability, create a static instead");
                     }
                 }
                 // If the reference has to be 'static, avoid in-place initialization
@@ -548,9 +550,9 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
         ty::TyEnum(def, _) if def.has_dtor() => {
             v.add_qualif(ConstQualif::NEEDS_DROP);
             if v.mode != Mode::Var {
-                v.tcx.sess.span_err(e.span,
-                                    &format!("{}s are not allowed to have destructors",
-                                             v.msg()));
+                span_err!(v.tcx.sess, e.span, E0493,
+                          "{}s are not allowed to have destructors",
+                          v.msg());
             }
         }
         _ => {}
@@ -567,8 +569,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                             "user-defined operators are not allowed in {}s", v.msg());
             }
         }
-        hir::ExprBox(..) |
-        hir::ExprUnary(hir::UnUniq, _) => {
+        hir::ExprBox(_) => {
             v.add_qualif(ConstQualif::NOT_CONST);
             if v.mode != Mode::Var {
                 span_err!(v.tcx.sess, e.span, E0010,
@@ -659,7 +660,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                                              doesn't point to a constant");
                     }
                 }
-                Some(def::DefLocal(_)) if v.mode == Mode::ConstFn => {
+                Some(def::DefLocal(..)) if v.mode == Mode::ConstFn => {
                     // Sadly, we can't determine whether the types are zero-sized.
                     v.add_qualif(ConstQualif::NOT_CONST | ConstQualif::NON_ZERO_SIZED);
                 }
@@ -678,7 +679,6 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
             let mut callee = &**callee;
             loop {
                 callee = match callee.node {
-                    hir::ExprParen(ref inner) => &**inner,
                     hir::ExprBlock(ref block) => match block.expr {
                         Some(ref tail) => &**tail,
                         None => break
@@ -710,10 +710,27 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
             if !is_const {
                 v.add_qualif(ConstQualif::NOT_CONST);
                 if v.mode != Mode::Var {
-                    span_err!(v.tcx.sess, e.span, E0015,
-                              "function calls in {}s are limited to \
-                               constant functions, \
-                               struct and enum constructors", v.msg());
+                    fn span_limited_call_error(tcx: &ty::ctxt, span: Span, s: &str) {
+                        span_err!(tcx.sess, span, E0015, "{}", s);
+                    }
+
+                    // FIXME(#24111) Remove this check when const fn stabilizes
+                    if let UnstableFeatures::Disallow = v.tcx.sess.opts.unstable_features {
+                        span_limited_call_error(&v.tcx, e.span,
+                                                &format!("function calls in {}s are limited to \
+                                                          struct and enum constructors",
+                                                         v.msg()));
+                        v.tcx.sess.span_note(e.span,
+                                             "a limited form of compile-time function \
+                                              evaluation is available on a nightly \
+                                              compiler via `const fn`");
+                    } else {
+                        span_limited_call_error(&v.tcx, e.span,
+                                                &format!("function calls in {}s are limited \
+                                                          to constant functions, \
+                                                          struct and enum constructors",
+                                                         v.msg()));
+                    }
                 }
             }
         }
@@ -763,7 +780,6 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
         hir::ExprField(..) |
         hir::ExprTupField(..) |
         hir::ExprVec(_) |
-        hir::ExprParen(..) |
         hir::ExprTup(..) => {}
 
         // Conditional control flow (possible to implement).
@@ -909,9 +925,9 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'tcx> {
                         // Borrowed statics can specifically *only* have their address taken,
                         // not any number of other borrows such as borrowing fields, reading
                         // elements of an array, etc.
-                        self.tcx.sess.span_err(borrow_span,
-                            "cannot refer to the interior of another \
-                             static, use a constant instead");
+                        span_err!(self.tcx.sess, borrow_span, E0494,
+                                  "cannot refer to the interior of another \
+                                   static, use a constant instead");
                     }
                     break;
                 }
index 8d592c9262958e26d4058c44416cdce7732b2906..f8786c7daaa80adf5fd9d7837d3f17de9b2376f1 100644 (file)
@@ -29,13 +29,13 @@ use middle::ty::*;
 use middle::ty;
 use std::cmp::Ordering;
 use std::fmt;
-use std::iter::{range_inclusive, FromIterator, IntoIterator, repeat};
-use std::slice;
+use std::iter::{FromIterator, IntoIterator, repeat};
 
 use rustc_front::hir;
 use rustc_front::hir::Pat;
 use rustc_front::visit::{self, Visitor, FnKind};
 use rustc_front::util as front_util;
+use rustc_back::slice;
 
 use syntax::ast::{self, DUMMY_NODE_ID, NodeId};
 use syntax::ast_util;
@@ -245,7 +245,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
                 let pat_ty = cx.tcx.pat_ty(p);
                 if let ty::TyEnum(edef, _) = pat_ty.sty {
                     let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
-                    if let Some(DefLocal(_)) = def {
+                    if let Some(DefLocal(..)) = def {
                         if edef.variants.iter().any(|variant|
                             variant.name == ident.node.name
                                 && variant.kind() == VariantKind::Unit
@@ -272,7 +272,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
 fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) {
     front_util::walk_pat(pat, |p| {
         if let hir::PatLit(ref expr) = p.node {
-            match eval_const_expr_partial(cx.tcx, &**expr, ExprTypeChecked) {
+            match eval_const_expr_partial(cx.tcx, &**expr, ExprTypeChecked, None) {
                 Ok(ConstVal::Float(f)) if f.is_nan() => {
                     span_warn!(cx.tcx.sess, p.span, E0003,
                                "unmatchable NaN in pattern, \
@@ -281,11 +281,10 @@ fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) {
                 Ok(_) => {}
 
                 Err(err) => {
-                    let subspan = p.span.lo <= err.span.lo && err.span.hi <= p.span.hi;
-                    cx.tcx.sess.span_err(err.span,
-                                         &format!("constant evaluation error: {}",
-                                                  err.description()));
-                    if !subspan {
+                    span_err!(cx.tcx.sess, err.span, E0471,
+                              "constant evaluation error: {}",
+                              err.description());
+                    if !p.span.contains(err.span) {
                         cx.tcx.sess.span_note(p.span,
                                               "in pattern here")
                     }
@@ -404,7 +403,7 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: hir:
 
 fn const_val_to_expr(value: &ConstVal) -> P<hir::Expr> {
     let node = match value {
-        &ConstVal::Bool(b) => hir::LitBool(b),
+        &ConstVal::Bool(b) => ast::LitBool(b),
         _ => unreachable!()
     };
     P(hir::Expr {
@@ -519,14 +518,14 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
 
         ty::TyEnum(adt, _) | ty::TyStruct(adt, _)  => {
             let v = adt.variant_of_ctor(ctor);
-            if let VariantKind::Dict = v.kind() {
+            if let VariantKind::Struct = v.kind() {
                 let field_pats: Vec<_> = v.fields.iter()
                     .zip(pats)
                     .filter(|&(_, ref pat)| pat.node != hir::PatWild(hir::PatWildSingle))
                     .map(|(field, pat)| Spanned {
                         span: DUMMY_SP,
                         node: hir::FieldPat {
-                            ident: ast::Ident::new(field.name),
+                            name: field.name,
                             pat: pat,
                             is_shorthand: false,
                         }
@@ -616,7 +615,7 @@ fn all_constructors(_cx: &MatchCheckCtxt, left_ty: Ty,
 
         ty::TyRef(_, ty::TypeAndMut { ty, .. }) => match ty.sty {
             ty::TySlice(_) =>
-                range_inclusive(0, max_slice_length).map(|length| Slice(length)).collect(),
+                (0..max_slice_length+1).map(|length| Slice(length)).collect(),
             _ => vec![Single]
         },
 
@@ -791,7 +790,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
             match left_ty.sty {
                 ty::TyArray(_, _) => vec!(Single),
                 _                      => if slice.is_some() {
-                    range_inclusive(before.len() + after.len(), max_slice_length)
+                    (before.len() + after.len()..max_slice_length+1)
                         .map(|length| Slice(length))
                         .collect()
                 } else {
@@ -910,7 +909,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             let def_variant = adt.variant_of_def(def);
             if variant.did == def_variant.did {
                 Some(variant.fields.iter().map(|sf| {
-                    match pattern_fields.iter().find(|f| f.node.ident.name == sf.name) {
+                    match pattern_fields.iter().find(|f| f.node.name == sf.name) {
                         Some(ref f) => &*f.node.pat,
                         _ => DUMMY_WILD_PAT
                     }
index aa1b7457aa90a39d925fd377e17cd4e4599de0cf..b9f8f20536a132ce2272958707a2e708bf076815 100644 (file)
@@ -32,8 +32,8 @@ struct CheckNoAsm<'a> {
 impl<'a, 'v> Visitor<'v> for CheckNoAsm<'a> {
     fn visit_expr(&mut self, e: &ast::Expr) {
         match e.node {
-            ast::ExprInlineAsm(_) => self.sess.span_err(e.span,
-                                                        "asm! is unsupported on this target"),
+            ast::ExprInlineAsm(_) => span_err!(self.sess, e.span, E0472,
+                                               "asm! is unsupported on this target"),
             _ => {},
         }
         visit::walk_expr(self, e)
index 942d8313ec24ee566e289e853802ea97cd4f3823..45671367a5c3c992e2f937354874d79dc8274a10 100644 (file)
@@ -54,7 +54,7 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> {
                         let mut recursion_visitor =
                             CheckItemRecursionVisitor::new(self, &variant.span);
                         recursion_visitor.populate_enum_discriminants(enum_def);
-                        recursion_visitor.visit_variant(variant, generics);
+                        recursion_visitor.visit_variant(variant, generics, it.id);
                     }
                 }
             }
@@ -168,7 +168,7 @@ impl<'a, 'ast: 'a> CheckItemRecursionVisitor<'a, 'ast> {
         let mut discriminant_map = self.discriminant_map.borrow_mut();
         match enum_definition.variants.first() {
             None => { return; }
-            Some(variant) if discriminant_map.contains_key(&variant.node.id) => {
+            Some(variant) if discriminant_map.contains_key(&variant.node.data.id()) => {
                 return;
             }
             _ => {}
@@ -177,7 +177,7 @@ impl<'a, 'ast: 'a> CheckItemRecursionVisitor<'a, 'ast> {
         // Go through all the variants.
         let mut variant_stack: Vec<ast::NodeId> = Vec::new();
         for variant in enum_definition.variants.iter().rev() {
-            variant_stack.push(variant.node.id);
+            variant_stack.push(variant.node.data.id());
             // When we find an expression, every variant currently on the stack
             // is affected by that expression.
             if let Some(ref expr) = variant.node.disr_expr {
@@ -201,14 +201,14 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
     }
 
     fn visit_enum_def(&mut self, enum_definition: &'ast hir::EnumDef,
-                      generics: &'ast hir::Generics) {
+                      generics: &'ast hir::Generics, item_id: ast::NodeId, _: Span) {
         self.populate_enum_discriminants(enum_definition);
-        visit::walk_enum_def(self, enum_definition, generics);
+        visit::walk_enum_def(self, enum_definition, generics, item_id);
     }
 
     fn visit_variant(&mut self, variant: &'ast hir::Variant,
-                     _: &'ast hir::Generics) {
-        let variant_id = variant.node.id;
+                     _: &'ast hir::Generics, _: ast::NodeId) {
+        let variant_id = variant.node.data.id();
         let maybe_expr;
         if let Some(get_expr) = self.discriminant_map.borrow().get(&variant_id) {
             // This is necessary because we need to let the `discriminant_map`
@@ -240,37 +240,44 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
                 match self.def_map.borrow().get(&e.id).map(|d| d.base_def) {
                     Some(DefStatic(def_id, _)) |
                     Some(DefAssociatedConst(def_id)) |
-                    Some(DefConst(def_id)) if def_id.is_local() => {
-                        match self.ast_map.get(def_id.node) {
-                          ast_map::NodeItem(item) =>
-                            self.visit_item(item),
-                          ast_map::NodeTraitItem(item) =>
-                            self.visit_trait_item(item),
-                          ast_map::NodeImplItem(item) =>
-                            self.visit_impl_item(item),
-                          ast_map::NodeForeignItem(_) => {},
-                          _ => {
-                              self.sess.span_bug(
-                                  e.span,
-                                  &format!("expected item, found {}",
-                                           self.ast_map.node_to_string(def_id.node)));
-                          }
+                    Some(DefConst(def_id)) => {
+                        if let Some(node_id) = self.ast_map.as_local_node_id(def_id) {
+                            match self.ast_map.get(node_id) {
+                                ast_map::NodeItem(item) =>
+                                    self.visit_item(item),
+                                ast_map::NodeTraitItem(item) =>
+                                    self.visit_trait_item(item),
+                                ast_map::NodeImplItem(item) =>
+                                    self.visit_impl_item(item),
+                                ast_map::NodeForeignItem(_) => {},
+                                _ => {
+                                    self.sess.span_bug(
+                                        e.span,
+                                        &format!("expected item, found {}",
+                                                 self.ast_map.node_to_string(node_id)));
+                                }
+                            }
                         }
                     }
                     // For variants, we only want to check expressions that
                     // affect the specific variant used, but we need to check
                     // the whole enum definition to see what expression that
                     // might be (if any).
-                    Some(DefVariant(enum_id, variant_id, false)) if enum_id.is_local() => {
-                        if let hir::ItemEnum(ref enum_def, ref generics) =
-                               self.ast_map.expect_item(enum_id.local_id()).node {
-                            self.populate_enum_discriminants(enum_def);
-                            let variant = self.ast_map.expect_variant(variant_id.local_id());
-                            self.visit_variant(variant, generics);
-                        } else {
-                            self.sess.span_bug(e.span,
-                                "`check_static_recursion` found \
-                                 non-enum in DefVariant");
+                    Some(DefVariant(enum_id, variant_id, false)) => {
+                        if let Some(enum_node_id) = self.ast_map.as_local_node_id(enum_id) {
+                            if let hir::ItemEnum(ref enum_def, ref generics) =
+                                self.ast_map.expect_item(enum_node_id).node
+                            {
+                                self.populate_enum_discriminants(enum_def);
+                                let enum_id = self.ast_map.as_local_node_id(enum_id).unwrap();
+                                let variant_id = self.ast_map.as_local_node_id(variant_id).unwrap();
+                                let variant = self.ast_map.expect_variant(variant_id);
+                                self.visit_variant(variant, generics, enum_id);
+                            } else {
+                                self.sess.span_bug(e.span,
+                                                   "`check_static_recursion` found \
+                                                    non-enum in DefVariant");
+                            }
                         }
                     }
                     _ => ()
index e1cf6ace8432eaa2af09b87f7546806517a69a89..1651e71c49a2aec1449b91a8de689298d6baf727 100644 (file)
@@ -19,13 +19,14 @@ use front::map::blocks::FnLikeNode;
 use metadata::csearch;
 use metadata::inline::InlinedItem;
 use middle::{astencode, def, infer, subst, traits};
-use middle::def_id::{DefId};
+use middle::def_id::DefId;
 use middle::pat_util::def_to_path;
 use middle::ty::{self, Ty};
 use middle::astconv_util::ast_ty_to_prim_ty;
 use util::num::ToPrimitive;
+use util::nodemap::NodeMap;
 
-use syntax::ast;
+use syntax::{ast, abi};
 use rustc_front::hir::Expr;
 use rustc_front::hir;
 use rustc_front::visit::FnKind;
@@ -38,6 +39,7 @@ use std::borrow::{Cow, IntoCow};
 use std::num::wrapping::OverflowingOps;
 use std::cmp::Ordering;
 use std::collections::hash_map::Entry::Vacant;
+use std::mem::transmute;
 use std::{i8, i16, i32, i64, u8, u16, u32, u64};
 use std::rc::Rc;
 
@@ -62,48 +64,27 @@ fn lookup_variant_by_id<'a>(tcx: &'a ty::ctxt,
     fn variant_expr<'a>(variants: &'a [P<hir::Variant>], id: ast::NodeId)
                         -> Option<&'a Expr> {
         for variant in variants {
-            if variant.node.id == id {
+            if variant.node.data.id() == id {
                 return variant.node.disr_expr.as_ref().map(|e| &**e);
             }
         }
         None
     }
 
-    if enum_def.is_local() {
-        match tcx.map.find(enum_def.node) {
+    if let Some(enum_node_id) = tcx.map.as_local_node_id(enum_def) {
+        let variant_node_id = tcx.map.as_local_node_id(variant_def).unwrap();
+        match tcx.map.find(enum_node_id) {
             None => None,
             Some(ast_map::NodeItem(it)) => match it.node {
                 hir::ItemEnum(hir::EnumDef { ref variants }, _) => {
-                    variant_expr(&variants[..], variant_def.node)
+                    variant_expr(&variants[..], variant_node_id)
                 }
                 _ => None
             },
             Some(_) => None
         }
     } else {
-        match tcx.extern_const_variants.borrow().get(&variant_def) {
-            Some(&ast::DUMMY_NODE_ID) => return None,
-            Some(&expr_id) => {
-                return Some(tcx.map.expect_expr(expr_id));
-            }
-            None => {}
-        }
-        let expr_id = match csearch::maybe_get_item_ast(tcx, enum_def,
-            Box::new(|a, b, c, d| astencode::decode_inlined_item(a, b, c, d))) {
-            csearch::FoundAst::Found(&InlinedItem::Item(ref item)) => match item.node {
-                hir::ItemEnum(hir::EnumDef { ref variants }, _) => {
-                    // NOTE this doesn't do the right thing, it compares inlined
-                    // NodeId's to the original variant_def's NodeId, but they
-                    // come from different crates, so they will likely never match.
-                    variant_expr(&variants[..], variant_def.node).map(|e| e.id)
-                }
-                _ => None
-            },
-            _ => None
-        };
-        tcx.extern_const_variants.borrow_mut().insert(variant_def,
-                                                      expr_id.unwrap_or(ast::DUMMY_NODE_ID));
-        expr_id.map(|id| tcx.map.expect_expr(id))
+        None
     }
 }
 
@@ -111,8 +92,8 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
                                         def_id: DefId,
                                         maybe_ref_id: Option<ast::NodeId>)
                                         -> Option<&'tcx Expr> {
-    if def_id.is_local() {
-        match tcx.map.find(def_id.node) {
+    if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
+        match tcx.map.find(node_id) {
             None => None,
             Some(ast_map::NodeItem(it)) => match it.node {
                 hir::ItemConst(_, ref const_expr) => {
@@ -164,7 +145,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
         }
         let mut used_ref_id = false;
         let expr_id = match csearch::maybe_get_item_ast(tcx, def_id,
-            Box::new(|a, b, c, d| astencode::decode_inlined_item(a, b, c, d))) {
+            Box::new(astencode::decode_inlined_item)) {
             csearch::FoundAst::Found(&InlinedItem::Item(ref item)) => match item.node {
                 hir::ItemConst(_, ref const_expr) => Some(const_expr.id),
                 _ => None
@@ -220,7 +201,7 @@ fn inline_const_fn_from_external_crate(tcx: &ty::ctxt, def_id: DefId)
     }
 
     let fn_id = match csearch::maybe_get_item_ast(tcx, def_id,
-        box |a, b, c, d| astencode::decode_inlined_item(a, b, c, d)) {
+        box astencode::decode_inlined_item) {
         csearch::FoundAst::Found(&InlinedItem::Item(ref item)) => Some(item.id),
         csearch::FoundAst::Found(&InlinedItem::ImplItem(_, ref item)) => Some(item.id),
         _ => None
@@ -233,14 +214,14 @@ fn inline_const_fn_from_external_crate(tcx: &ty::ctxt, def_id: DefId)
 pub fn lookup_const_fn_by_id<'tcx>(tcx: &ty::ctxt<'tcx>, def_id: DefId)
                                    -> Option<FnLikeNode<'tcx>>
 {
-    let fn_id = if !def_id.is_local() {
+    let fn_id = if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
+        node_id
+    } else {
         if let Some(fn_id) = inline_const_fn_from_external_crate(tcx, def_id) {
             fn_id
         } else {
             return None;
         }
-    } else {
-        def_id.node
     };
 
     let fn_like = match FnLikeNode::from_node(tcx.map.get(fn_id)) {
@@ -263,7 +244,7 @@ pub fn lookup_const_fn_by_id<'tcx>(tcx: &ty::ctxt<'tcx>, def_id: DefId)
     }
 }
 
-#[derive(Clone, PartialEq)]
+#[derive(Clone, Debug)]
 pub enum ConstVal {
     Float(f64),
     Int(i64),
@@ -273,6 +254,28 @@ pub enum ConstVal {
     Bool(bool),
     Struct(ast::NodeId),
     Tuple(ast::NodeId),
+    Function(DefId),
+}
+
+/// Note that equality for `ConstVal` means that the it is the same
+/// constant, not that the rust values are equal. In particular, `NaN
+/// == NaN` (at least if it's the same NaN; distinct encodings for NaN
+/// are considering unequal).
+impl PartialEq for ConstVal {
+    fn eq(&self, other: &ConstVal) -> bool {
+        match (self, other) {
+            (&Float(a), &Float(b)) => unsafe{transmute::<_,u64>(a) == transmute::<_,u64>(b)},
+            (&Int(a), &Int(b)) => a == b,
+            (&Uint(a), &Uint(b)) => a == b,
+            (&Str(ref a), &Str(ref b)) => a == b,
+            (&ByteStr(ref a), &ByteStr(ref b)) => a == b,
+            (&Bool(a), &Bool(b)) => a == b,
+            (&Struct(a), &Struct(b)) => a == b,
+            (&Tuple(a), &Tuple(b)) => a == b,
+            (&Function(a), &Function(b)) => a == b,
+            _ => false,
+        }
+    }
 }
 
 impl ConstVal {
@@ -287,6 +290,7 @@ impl ConstVal {
             Bool(_) => "boolean",
             Struct(_) => "struct",
             Tuple(_) => "tuple",
+            Function(_) => "function definition",
         }
     }
 }
@@ -314,7 +318,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<hir::Pat>
             let field_pats = fields.iter().map(|field| codemap::Spanned {
                 span: codemap::DUMMY_SP,
                 node: hir::FieldPat {
-                    ident: field.ident.node,
+                    name: field.name.node,
                     pat: const_expr_to_pat(tcx, &*field.expr, span),
                     is_shorthand: false,
                 },
@@ -349,12 +353,13 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<hir::Pat>
 }
 
 pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> ConstVal {
-    match eval_const_expr_partial(tcx, e, ExprTypeChecked) {
+    match eval_const_expr_partial(tcx, e, ExprTypeChecked, None) {
         Ok(r) => r,
         Err(s) => tcx.sess.span_fatal(s.span, &s.description())
     }
 }
 
+pub type FnArgMap<'a> = Option<&'a NodeMap<ConstVal>>;
 
 #[derive(Clone)]
 pub struct ConstEvalErr {
@@ -388,6 +393,7 @@ pub enum ErrKind {
     ShiftRightWithOverflow,
     MissingStructField,
     NonConstPath,
+    UnresolvedPath,
     ExpectedConstTuple,
     ExpectedConstStruct,
     TupleIndexOutOfBounds,
@@ -424,7 +430,8 @@ impl ConstEvalErr {
             ShiftLeftWithOverflow => "attempted left shift with overflow".into_cow(),
             ShiftRightWithOverflow => "attempted right shift with overflow".into_cow(),
             MissingStructField  => "nonexistent struct field".into_cow(),
-            NonConstPath        => "non-constant path in constant expr".into_cow(),
+            NonConstPath        => "non-constant path in constant expression".into_cow(),
+            UnresolvedPath => "unresolved path in constant expression".into_cow(),
             ExpectedConstTuple => "expected constant tuple".into_cow(),
             ExpectedConstStruct => "expected constant struct".into_cow(),
             TupleIndexOutOfBounds => "tuple index out of bounds".into_cow(),
@@ -466,35 +473,35 @@ pub enum IntTy { I8, I16, I32, I64 }
 pub enum UintTy { U8, U16, U32, U64 }
 
 impl IntTy {
-    pub fn from(tcx: &ty::ctxt, t: hir::IntTy) -> IntTy {
-        let t = if let hir::TyIs = t {
+    pub fn from(tcx: &ty::ctxt, t: ast::IntTy) -> IntTy {
+        let t = if let ast::TyIs = t {
             tcx.sess.target.int_type
         } else {
             t
         };
         match t {
-            hir::TyIs => unreachable!(),
-            hir::TyI8  => IntTy::I8,
-            hir::TyI16 => IntTy::I16,
-            hir::TyI32 => IntTy::I32,
-            hir::TyI64 => IntTy::I64,
+            ast::TyIs => unreachable!(),
+            ast::TyI8  => IntTy::I8,
+            ast::TyI16 => IntTy::I16,
+            ast::TyI32 => IntTy::I32,
+            ast::TyI64 => IntTy::I64,
         }
     }
 }
 
 impl UintTy {
-    pub fn from(tcx: &ty::ctxt, t: hir::UintTy) -> UintTy {
-        let t = if let hir::TyUs = t {
+    pub fn from(tcx: &ty::ctxt, t: ast::UintTy) -> UintTy {
+        let t = if let ast::TyUs = t {
             tcx.sess.target.uint_type
         } else {
             t
         };
         match t {
-            hir::TyUs => unreachable!(),
-            hir::TyU8  => UintTy::U8,
-            hir::TyU16 => UintTy::U16,
-            hir::TyU32 => UintTy::U32,
-            hir::TyU64 => UintTy::U64,
+            ast::TyUs => unreachable!(),
+            ast::TyU8  => UintTy::U8,
+            ast::TyU16 => UintTy::U16,
+            ast::TyU32 => UintTy::U32,
+            ast::TyU64 => UintTy::U64,
         }
     }
 }
@@ -736,7 +743,8 @@ pub_fn_checked_op!{ const_uint_checked_shr_via_int(a: u64, b: i64,.. UintTy) {
 /// computing the length of an array. (See also the FIXME above EvalHint.)
 pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
                                      e: &Expr,
-                                     ty_hint: EvalHint<'tcx>) -> EvalResult {
+                                     ty_hint: EvalHint<'tcx>,
+                                     fn_args: FnArgMap) -> EvalResult {
     fn fromb(b: bool) -> ConstVal { Int(b as i64) }
 
     // Try to compute the type of the expression based on the EvalHint.
@@ -773,7 +781,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
 
     let result = match e.node {
       hir::ExprUnary(hir::UnNeg, ref inner) => {
-        match try!(eval_const_expr_partial(tcx, &**inner, ty_hint)) {
+        match try!(eval_const_expr_partial(tcx, &**inner, ty_hint, fn_args)) {
           Float(f) => Float(-f),
           Int(n) =>  try!(const_int_checked_neg(n, e, expr_int_type)),
           Uint(i) => {
@@ -783,7 +791,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
         }
       }
       hir::ExprUnary(hir::UnNot, ref inner) => {
-        match try!(eval_const_expr_partial(tcx, &**inner, ty_hint)) {
+        match try!(eval_const_expr_partial(tcx, &**inner, ty_hint, fn_args)) {
           Int(i) => Int(!i),
           Uint(i) => const_uint_not(i, expr_uint_type),
           Bool(b) => Bool(!b),
@@ -801,8 +809,8 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
             }
             _ => ty_hint
         };
-        match (try!(eval_const_expr_partial(tcx, &**a, ty_hint)),
-               try!(eval_const_expr_partial(tcx, &**b, b_ty))) {
+        match (try!(eval_const_expr_partial(tcx, &**a, ty_hint, fn_args)),
+               try!(eval_const_expr_partial(tcx, &**b, b_ty, fn_args))) {
           (Float(a), Float(b)) => {
             match op.node {
               hir::BiAdd => Float(a + b),
@@ -909,18 +917,31 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
             }
         };
 
-        let val = try!(eval_const_expr_partial(tcx, &**base, base_hint));
+        let val = try!(eval_const_expr_partial(tcx, &**base, base_hint, fn_args));
         match cast_const(tcx, val, ety) {
             Ok(val) => val,
             Err(kind) => return Err(ConstEvalErr { span: e.span, kind: kind }),
         }
       }
       hir::ExprPath(..) => {
-          let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
+          let opt_def = if let Some(def) = tcx.def_map.borrow().get(&e.id) {
+              // After type-checking, def_map contains definition of the
+              // item referred to by the path. During type-checking, it
+              // can contain the raw output of path resolution, which
+              // might be a partially resolved path.
+              // FIXME: There's probably a better way to make sure we don't
+              // panic here.
+              if def.depth != 0 {
+                  signal!(e, UnresolvedPath);
+              }
+              Some(def.full_def())
+          } else {
+              None
+          };
           let (const_expr, const_ty) = match opt_def {
               Some(def::DefConst(def_id)) => {
-                  if def_id.is_local() {
-                      match tcx.map.find(def_id.node) {
+                  if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
+                      match tcx.map.find(node_id) {
                           Some(ast_map::NodeItem(it)) => match it.node {
                               hir::ItemConst(ref ty, ref expr) => {
                                   (Some(&**expr), Some(&**ty))
@@ -934,9 +955,9 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
                   }
               }
               Some(def::DefAssociatedConst(def_id)) => {
-                  if def_id.is_local() {
+                  if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
                       match tcx.impl_or_trait_item(def_id).container() {
-                          ty::TraitContainer(trait_id) => match tcx.map.find(def_id.node) {
+                          ty::TraitContainer(trait_id) => match tcx.map.find(node_id) {
                               Some(ast_map::NodeTraitItem(ti)) => match ti.node {
                                   hir::ConstTraitItem(ref ty, _) => {
                                       if let ExprTypeChecked = ty_hint {
@@ -954,7 +975,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
                               },
                               _ => (None, None)
                           },
-                          ty::ImplContainer(_) => match tcx.map.find(def_id.node) {
+                          ty::ImplContainer(_) => match tcx.map.find(node_id) {
                               Some(ast_map::NodeImplItem(ii)) => match ii.node {
                                   hir::ConstImplItem(ref ty, ref expr) => {
                                       (Some(&**expr), Some(&**ty))
@@ -974,6 +995,16 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
               Some(def::DefStruct(_)) => {
                   return Ok(ConstVal::Struct(e.id))
               }
+              Some(def::DefLocal(_, id)) => {
+                  debug!("DefLocal({:?}): {:?}", id, fn_args);
+                  if let Some(val) = fn_args.and_then(|args| args.get(&id)) {
+                      return Ok(val.clone());
+                  } else {
+                      (None, None)
+                  }
+              },
+              Some(def::DefFn(id, _)) => return Ok(Function(id)),
+              // FIXME: implement const methods?
               _ => (None, None)
           };
           let const_expr = match const_expr {
@@ -991,15 +1022,76 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
           } else {
               ty_hint
           };
-          try!(eval_const_expr_partial(tcx, const_expr, item_hint))
+          try!(eval_const_expr_partial(tcx, const_expr, item_hint, fn_args))
       }
+      hir::ExprCall(ref callee, ref args) => {
+          let sub_ty_hint = if let ExprTypeChecked = ty_hint {
+              ExprTypeChecked
+          } else {
+              UncheckedExprNoHint // we cannot reason about UncheckedExprHint here
+          };
+          let (
+              decl,
+              unsafety,
+              abi,
+              block,
+              constness,
+          ) = match try!(eval_const_expr_partial(tcx, callee, sub_ty_hint, fn_args)) {
+              Function(did) => if did.is_local() {
+                  match tcx.map.find(did.index.as_u32()) {
+                      Some(ast_map::NodeItem(it)) => match it.node {
+                          hir::ItemFn(
+                              ref decl,
+                              unsafety,
+                              constness,
+                              abi,
+                              _, // ducktype generics? types are funky in const_eval
+                              ref block,
+                          ) => (decl, unsafety, abi, block, constness),
+                          _ => signal!(e, NonConstPath),
+                      },
+                      _ => signal!(e, NonConstPath),
+                  }
+              } else {
+                  signal!(e, NonConstPath)
+              },
+              _ => signal!(e, NonConstPath),
+          };
+          if let ExprTypeChecked = ty_hint {
+              // no need to check for constness... either check_const
+              // already forbids this or we const eval over whatever
+              // we want
+          } else {
+              // we don't know much about the function, so we force it to be a const fn
+              // so compilation will fail later in case the const fn's body is not const
+              assert_eq!(constness, hir::Constness::Const)
+          }
+          assert_eq!(decl.inputs.len(), args.len());
+          assert_eq!(unsafety, hir::Unsafety::Normal);
+          assert_eq!(abi, abi::Abi::Rust);
+
+          let mut call_args = NodeMap();
+          for (arg, arg_expr) in decl.inputs.iter().zip(args.iter()) {
+              let arg_val = try!(eval_const_expr_partial(
+                  tcx,
+                  arg_expr,
+                  sub_ty_hint,
+                  fn_args
+              ));
+              debug!("const call arg: {:?}", arg);
+              let old = call_args.insert(arg.pat.id, arg_val);
+              assert!(old.is_none());
+          }
+          let result = block.expr.as_ref().unwrap();
+          debug!("const call({:?})", call_args);
+          try!(eval_const_expr_partial(tcx, &**result, ty_hint, Some(&call_args)))
+      },
       hir::ExprLit(ref lit) => {
           lit_to_const(&**lit, ety)
       }
-      hir::ExprParen(ref e) => try!(eval_const_expr_partial(tcx, &**e, ty_hint)),
       hir::ExprBlock(ref block) => {
         match block.expr {
-            Some(ref expr) => try!(eval_const_expr_partial(tcx, &**expr, ty_hint)),
+            Some(ref expr) => try!(eval_const_expr_partial(tcx, &**expr, ty_hint, fn_args)),
             None => Int(0)
         }
       }
@@ -1011,11 +1103,11 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
         } else {
             UncheckedExprNoHint
         };
-        if let Ok(c) = eval_const_expr_partial(tcx, base, base_hint) {
+        if let Ok(c) = eval_const_expr_partial(tcx, base, base_hint, fn_args) {
             if let Tuple(tup_id) = c {
                 if let hir::ExprTup(ref fields) = tcx.map.expect_expr(tup_id).node {
                     if index.node < fields.len() {
-                        return eval_const_expr_partial(tcx, &fields[index.node], base_hint)
+                        return eval_const_expr_partial(tcx, &fields[index.node], base_hint, fn_args)
                     } else {
                         signal!(e, TupleIndexOutOfBounds);
                     }
@@ -1036,14 +1128,14 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
         } else {
             UncheckedExprNoHint
         };
-        if let Ok(c) = eval_const_expr_partial(tcx, base, base_hint) {
+        if let Ok(c) = eval_const_expr_partial(tcx, base, base_hint, fn_args) {
             if let Struct(struct_id) = c {
                 if let hir::ExprStruct(_, ref fields, _) = tcx.map.expect_expr(struct_id).node {
                     // Check that the given field exists and evaluate it
                     // if the idents are compared run-pass/issue-19244 fails
-                    if let Some(f) = fields.iter().find(|f| f.ident.node.name
-                                                         == field_name.node.name) {
-                        return eval_const_expr_partial(tcx, &*f.expr, base_hint)
+                    if let Some(f) = fields.iter().find(|f| f.name.node
+                                                         == field_name.node) {
+                        return eval_const_expr_partial(tcx, &*f.expr, base_hint, fn_args)
                     } else {
                         signal!(e, MissingStructField);
                     }
@@ -1110,7 +1202,7 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
     match selection {
         traits::VtableImpl(ref impl_data) => {
             match tcx.associated_consts(impl_data.impl_def_id)
-                     .iter().find(|ic| ic.name == ti.ident.name) {
+                     .iter().find(|ic| ic.name == ti.name) {
                 Some(ic) => lookup_const_by_id(tcx, ic.def_id, None),
                 None => match ti.node {
                     hir::ConstTraitItem(_, Some(ref expr)) => Some(&*expr),
@@ -1141,60 +1233,60 @@ fn cast_const<'tcx>(tcx: &ty::ctxt<'tcx>, val: ConstVal, ty: Ty) -> CastResult {
 
     // Issue #23890: If isize/usize, then dispatch to appropriate target representation type
     match (&ty.sty, tcx.sess.target.int_type, tcx.sess.target.uint_type) {
-        (&ty::TyInt(hir::TyIs), hir::TyI32, _) => return convert_val!(i32, Int, i64),
-        (&ty::TyInt(hir::TyIs), hir::TyI64, _) => return convert_val!(i64, Int, i64),
-        (&ty::TyInt(hir::TyIs), _, _) => panic!("unexpected target.int_type"),
+        (&ty::TyInt(ast::TyIs), ast::TyI32, _) => return convert_val!(i32, Int, i64),
+        (&ty::TyInt(ast::TyIs), ast::TyI64, _) => return convert_val!(i64, Int, i64),
+        (&ty::TyInt(ast::TyIs), _, _) => panic!("unexpected target.int_type"),
 
-        (&ty::TyUint(hir::TyUs), _, hir::TyU32) => return convert_val!(u32, Uint, u64),
-        (&ty::TyUint(hir::TyUs), _, hir::TyU64) => return convert_val!(u64, Uint, u64),
-        (&ty::TyUint(hir::TyUs), _, _) => panic!("unexpected target.uint_type"),
+        (&ty::TyUint(ast::TyUs), _, ast::TyU32) => return convert_val!(u32, Uint, u64),
+        (&ty::TyUint(ast::TyUs), _, ast::TyU64) => return convert_val!(u64, Uint, u64),
+        (&ty::TyUint(ast::TyUs), _, _) => panic!("unexpected target.uint_type"),
 
         _ => {}
     }
 
     match ty.sty {
-        ty::TyInt(hir::TyIs) => unreachable!(),
-        ty::TyUint(hir::TyUs) => unreachable!(),
+        ty::TyInt(ast::TyIs) => unreachable!(),
+        ty::TyUint(ast::TyUs) => unreachable!(),
 
-        ty::TyInt(hir::TyI8) => convert_val!(i8, Int, i64),
-        ty::TyInt(hir::TyI16) => convert_val!(i16, Int, i64),
-        ty::TyInt(hir::TyI32) => convert_val!(i32, Int, i64),
-        ty::TyInt(hir::TyI64) => convert_val!(i64, Int, i64),
+        ty::TyInt(ast::TyI8) => convert_val!(i8, Int, i64),
+        ty::TyInt(ast::TyI16) => convert_val!(i16, Int, i64),
+        ty::TyInt(ast::TyI32) => convert_val!(i32, Int, i64),
+        ty::TyInt(ast::TyI64) => convert_val!(i64, Int, i64),
 
-        ty::TyUint(hir::TyU8) => convert_val!(u8, Uint, u64),
-        ty::TyUint(hir::TyU16) => convert_val!(u16, Uint, u64),
-        ty::TyUint(hir::TyU32) => convert_val!(u32, Uint, u64),
-        ty::TyUint(hir::TyU64) => convert_val!(u64, Uint, u64),
+        ty::TyUint(ast::TyU8) => convert_val!(u8, Uint, u64),
+        ty::TyUint(ast::TyU16) => convert_val!(u16, Uint, u64),
+        ty::TyUint(ast::TyU32) => convert_val!(u32, Uint, u64),
+        ty::TyUint(ast::TyU64) => convert_val!(u64, Uint, u64),
 
-        ty::TyFloat(hir::TyF32) => convert_val!(f32, Float, f64),
-        ty::TyFloat(hir::TyF64) => convert_val!(f64, Float, f64),
+        ty::TyFloat(ast::TyF32) => convert_val!(f32, Float, f64),
+        ty::TyFloat(ast::TyF64) => convert_val!(f64, Float, f64),
         _ => Err(ErrKind::CannotCast),
     }
 }
 
-fn lit_to_const(lit: &hir::Lit, ty_hint: Option<Ty>) -> ConstVal {
+fn lit_to_const(lit: &ast::Lit, ty_hint: Option<Ty>) -> ConstVal {
     match lit.node {
-        hir::LitStr(ref s, _) => Str((*s).clone()),
-        hir::LitByteStr(ref data) => {
+        ast::LitStr(ref s, _) => Str((*s).clone()),
+        ast::LitByteStr(ref data) => {
             ByteStr(data.clone())
         }
-        hir::LitByte(n) => Uint(n as u64),
-        hir::LitChar(n) => Uint(n as u64),
-        hir::LitInt(n, hir::SignedIntLit(_, hir::Plus)) => Int(n as i64),
-        hir::LitInt(n, hir::UnsuffixedIntLit(hir::Plus)) => {
+        ast::LitByte(n) => Uint(n as u64),
+        ast::LitChar(n) => Uint(n as u64),
+        ast::LitInt(n, ast::SignedIntLit(_, ast::Plus)) => Int(n as i64),
+        ast::LitInt(n, ast::UnsuffixedIntLit(ast::Plus)) => {
             match ty_hint.map(|ty| &ty.sty) {
                 Some(&ty::TyUint(_)) => Uint(n),
                 _ => Int(n as i64)
             }
         }
-        hir::LitInt(n, hir::SignedIntLit(_, hir::Minus)) |
-        hir::LitInt(n, hir::UnsuffixedIntLit(hir::Minus)) => Int(-(n as i64)),
-        hir::LitInt(n, hir::UnsignedIntLit(_)) => Uint(n),
-        hir::LitFloat(ref n, _) |
-        hir::LitFloatUnsuffixed(ref n) => {
+        ast::LitInt(n, ast::SignedIntLit(_, ast::Minus)) |
+        ast::LitInt(n, ast::UnsuffixedIntLit(ast::Minus)) => Int(-(n as i64)),
+        ast::LitInt(n, ast::UnsignedIntLit(_)) => Uint(n),
+        ast::LitFloat(ref n, _) |
+        ast::LitFloatUnsuffixed(ref n) => {
             Float(n.parse::<f64>().unwrap() as f64)
         }
-        hir::LitBool(b) => Bool(b)
+        ast::LitBool(b) => Bool(b)
     }
 }
 
@@ -1222,14 +1314,14 @@ pub fn compare_const_vals(a: &ConstVal, b: &ConstVal) -> Option<Ordering> {
 pub fn compare_lit_exprs<'tcx>(tcx: &ty::ctxt<'tcx>,
                                a: &Expr,
                                b: &Expr) -> Option<Ordering> {
-    let a = match eval_const_expr_partial(tcx, a, ExprTypeChecked) {
+    let a = match eval_const_expr_partial(tcx, a, ExprTypeChecked, None) {
         Ok(a) => a,
         Err(e) => {
             tcx.sess.span_err(a.span, &e.description());
             return None;
         }
     };
-    let b = match eval_const_expr_partial(tcx, b, ExprTypeChecked) {
+    let b = match eval_const_expr_partial(tcx, b, ExprTypeChecked, None) {
         Ok(b) => b,
         Err(e) => {
             tcx.sess.span_err(b.span, &e.description());
index 14ba241f62b0f1bfabdb6dd0a94a68eaef0fa1c0..caedc811842a0757cfc1a82a23e877f75fb3e65c 100644 (file)
@@ -24,6 +24,7 @@ use std::usize;
 use syntax::ast;
 use syntax::ast_util::IdRange;
 use syntax::print::pp;
+use syntax::print::pprust::PrintState;
 use util::nodemap::NodeMap;
 use rustc_front::hir;
 use rustc_front::visit;
@@ -113,7 +114,7 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O
            ps: &mut pprust::State,
            node: pprust::AnnNode) -> io::Result<()> {
         let id = match node {
-            pprust::NodeIdent(_) | pprust::NodeName(_) => 0,
+            pprust::NodeName(_) => 0,
             pprust::NodeExpr(expr) => expr.id,
             pprust::NodeBlock(blk) => blk.id,
             pprust::NodeItem(_) | pprust::NodeSubItem(_) => 0,
index ed9ca48b39ca2b209cce82a105e0130fae0a3060..8c995ca29235cc699ecedb544ce9ac8ded76dceb 100644 (file)
@@ -15,7 +15,6 @@
 use front::map as ast_map;
 use rustc_front::hir;
 use rustc_front::visit::{self, Visitor};
-use rustc_front::attr::{self, AttrMetaMethods};
 
 use middle::{def, pat_util, privacy, ty};
 use middle::def_id::{DefId};
@@ -24,22 +23,21 @@ use util::nodemap::NodeSet;
 
 use std::collections::HashSet;
 use syntax::{ast, codemap};
+use syntax::attr::{self, AttrMetaMethods};
 
 // Any local node that may call something in its body block should be
 // explored. For example, if it's a live NodeItem that is a
 // function, then we should explore its block to check for codes that
 // may need to be marked as live.
-fn should_explore(tcx: &ty::ctxt, def_id: DefId) -> bool {
-    if !def_id.is_local() {
-        return false;
-    }
-
-    match tcx.map.find(def_id.node) {
-        Some(ast_map::NodeItem(..))
-        | Some(ast_map::NodeImplItem(..))
-        | Some(ast_map::NodeForeignItem(..))
-        | Some(ast_map::NodeTraitItem(..)) => true,
-        _ => false
+fn should_explore(tcx: &ty::ctxt, node_id: ast::NodeId) -> bool {
+    match tcx.map.find(node_id) {
+        Some(ast_map::NodeItem(..)) |
+        Some(ast_map::NodeImplItem(..)) |
+        Some(ast_map::NodeForeignItem(..)) |
+        Some(ast_map::NodeTraitItem(..)) =>
+            true,
+        _ =>
+            false
     }
 }
 
@@ -50,7 +48,7 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> {
     struct_has_extern_repr: bool,
     ignore_non_const_paths: bool,
     inherited_pub_visibility: bool,
-    ignore_variant_stack: Vec<ast::NodeId>,
+    ignore_variant_stack: Vec<DefId>,
 }
 
 impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
@@ -68,10 +66,19 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
     }
 
     fn check_def_id(&mut self, def_id: DefId) {
-        if should_explore(self.tcx, def_id) {
-            self.worklist.push(def_id.node);
+        if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
+            if should_explore(self.tcx, node_id) {
+                self.worklist.push(node_id);
+            }
+            self.live_symbols.insert(node_id);
+        }
+    }
+
+    fn insert_def_id(&mut self, def_id: DefId) {
+        if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
+            debug_assert!(!should_explore(self.tcx, node_id));
+            self.live_symbols.insert(node_id);
         }
-        self.live_symbols.insert(def_id.node);
     }
 
     fn lookup_and_handle_definition(&mut self, id: &ast::NodeId) {
@@ -88,13 +95,14 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
         self.tcx.def_map.borrow().get(id).map(|def| {
             match def.full_def() {
                 def::DefConst(_) | def::DefAssociatedConst(..) => {
-                    self.check_def_id(def.def_id())
+                    self.check_def_id(def.def_id());
                 }
                 _ if self.ignore_non_const_paths => (),
                 def::DefPrimTy(_) => (),
+                def::DefSelfTy(..) => (),
                 def::DefVariant(enum_id, variant_id, _) => {
                     self.check_def_id(enum_id);
-                    if !self.ignore_variant_stack.contains(&variant_id.node) {
+                    if !self.ignore_variant_stack.contains(&variant_id) {
                         self.check_def_id(variant_id);
                     }
                 }
@@ -113,7 +121,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
 
     fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) {
         if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(lhs).sty {
-            self.live_symbols.insert(def.struct_variant().field_named(name).did.node);
+            self.insert_def_id(def.struct_variant().field_named(name).did);
         } else {
             self.tcx.sess.span_bug(lhs.span, "named field access on non-struct")
         }
@@ -121,7 +129,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
 
     fn handle_tup_field_access(&mut self, lhs: &hir::Expr, idx: usize) {
         if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(lhs).sty {
-            self.live_symbols.insert(def.struct_variant().fields[idx].did.node);
+            self.insert_def_id(def.struct_variant().fields[idx].did);
         }
     }
 
@@ -137,7 +145,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
             if let hir::PatWild(hir::PatWildSingle) = pat.node.pat.node {
                 continue;
             }
-            self.live_symbols.insert(variant.field_named(pat.node.ident.name).did.node);
+            self.insert_def_id(variant.field_named(pat.node.name).did);
         }
     }
 
@@ -207,11 +215,11 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
 
 impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
 
-    fn visit_struct_def(&mut self, def: &hir::StructDef, _: ast::Ident,
-                        _: &hir::Generics, _: ast::NodeId) {
+    fn visit_variant_data(&mut self, def: &hir::VariantData, _: ast::Name,
+                        _: &hir::Generics, _: ast::NodeId, _: codemap::Span) {
         let has_extern_repr = self.struct_has_extern_repr;
         let inherited_pub_visibility = self.inherited_pub_visibility;
-        let live_fields = def.fields.iter().filter(|f| {
+        let live_fields = def.fields().iter().filter(|f| {
             has_extern_repr || inherited_pub_visibility || match f.node.kind {
                 hir::NamedField(_, hir::Public) => true,
                 _ => false
@@ -227,8 +235,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
             hir::ExprMethodCall(..) => {
                 self.lookup_and_handle_method(expr.id);
             }
-            hir::ExprField(ref lhs, ref ident) => {
-                self.handle_field_access(&**lhs, ident.node.name);
+            hir::ExprField(ref lhs, ref name) => {
+                self.handle_field_access(&**lhs, name.node);
             }
             hir::ExprTupField(ref lhs, idx) => {
                 self.handle_tup_field_access(&**lhs, idx.node);
@@ -279,19 +287,24 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
         visit::walk_path(self, path);
     }
 
+    fn visit_path_list_item(&mut self, path: &hir::Path, item: &hir::PathListItem) {
+        self.lookup_and_handle_definition(&item.node.id());
+        visit::walk_path_list_item(self, path, item);
+    }
+
     fn visit_item(&mut self, _: &hir::Item) {
         // Do not recurse into items. These items will be added to the
         // worklist and recursed into manually if necessary.
     }
 }
 
-fn has_allow_dead_code_or_lang_attr(attrs: &[hir::Attribute]) -> bool {
+fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool {
     if attr::contains_name(attrs, "lang") {
         return true;
     }
 
     let dead_code = lint::builtin::DEAD_CODE.name_lower();
-    for attr in lint::gather_attrs_from_hir(attrs) {
+    for attr in lint::gather_attrs(attrs) {
         match attr {
             Ok((ref name, lint::Allow, _))
                 if &name[..] == dead_code => return true,
@@ -326,7 +339,8 @@ impl<'v> Visitor<'v> for LifeSeeder {
         }
         match item.node {
             hir::ItemEnum(ref enum_def, _) if allow_dead_code => {
-                self.worklist.extend(enum_def.variants.iter().map(|variant| variant.node.id));
+                self.worklist.extend(enum_def.variants.iter()
+                                                      .map(|variant| variant.node.data.id()));
             }
             hir::ItemTrait(_, _, _, ref trait_items) => {
                 for trait_item in trait_items {
@@ -413,7 +427,9 @@ fn find_live(tcx: &ty::ctxt,
 
 fn get_struct_ctor_id(item: &hir::Item) -> Option<ast::NodeId> {
     match item.node {
-        hir::ItemStruct(ref struct_def, _) => struct_def.ctor_id,
+        hir::ItemStruct(ref struct_def, _) if !struct_def.is_struct() => {
+            Some(struct_def.id())
+        }
         _ => None
     }
 }
@@ -438,7 +454,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
     }
 
     fn should_warn_about_field(&mut self, node: &hir::StructField_) -> bool {
-        let is_named = node.ident().is_some();
+        let is_named = node.name().is_some();
         let field_type = self.tcx.node_id_to_type(node.id);
         let is_marker_field = match field_type.ty_to_def_id() {
             Some(def_id) => self.tcx.lang_items.items().any(|(_, item)| *item == Some(def_id)),
@@ -451,7 +467,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
     }
 
     fn should_warn_about_variant(&mut self, variant: &hir::Variant_) -> bool {
-        !self.symbol_is_live(variant.id, None)
+        !self.symbol_is_live(variant.data.id(), None)
             && !has_allow_dead_code_or_lang_attr(&variant.attrs)
     }
 
@@ -464,8 +480,10 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
     // `ctor_id`. On the other hand, in a statement like
     // `type <ident> <generics> = <ty>;` where <ty> refers to a struct_ctor,
     // DefMap maps <ty> to `id` instead.
-    fn symbol_is_live(&mut self, id: ast::NodeId,
-                      ctor_id: Option<ast::NodeId>) -> bool {
+    fn symbol_is_live(&mut self,
+                      id: ast::NodeId,
+                      ctor_id: Option<ast::NodeId>)
+                      -> bool {
         if self.live_symbols.contains(&id)
            || ctor_id.map_or(false,
                              |ctor| self.live_symbols.contains(&ctor)) {
@@ -476,14 +494,16 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
         // method of a private type is used, but the type itself is never
         // called directly.
         let impl_items = self.tcx.impl_items.borrow();
-        match self.tcx.inherent_impls.borrow().get(&DefId::local(id)) {
+        match self.tcx.inherent_impls.borrow().get(&self.tcx.map.local_def_id(id)) {
             None => (),
             Some(impl_list) => {
                 for impl_did in impl_list.iter() {
                     for item_did in impl_items.get(impl_did).unwrap().iter() {
-                        if self.live_symbols.contains(&item_did.def_id()
-                                                               .node) {
-                            return true;
+                        if let Some(item_node_id) =
+                                self.tcx.map.as_local_node_id(item_did.def_id()) {
+                            if self.live_symbols.contains(&item_node_id) {
+                                return true;
+                            }
                         }
                     }
                 }
@@ -515,7 +535,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
             self.warn_dead_code(
                 item.id,
                 item.span,
-                item.ident.name,
+                item.name,
                 item.node.descriptive_variant()
             );
         } else {
@@ -523,8 +543,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
                 hir::ItemEnum(ref enum_def, _) => {
                     for variant in &enum_def.variants {
                         if self.should_warn_about_variant(&variant.node) {
-                            self.warn_dead_code(variant.node.id, variant.span,
-                                                variant.node.name.name, "variant");
+                            self.warn_dead_code(variant.node.data.id(), variant.span,
+                                                variant.node.name, "variant");
                         }
                     }
                 },
@@ -536,7 +556,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
 
     fn visit_foreign_item(&mut self, fi: &hir::ForeignItem) {
         if !self.symbol_is_live(fi.id, None) {
-            self.warn_dead_code(fi.id, fi.span, fi.ident.name, fi.node.descriptive_variant());
+            self.warn_dead_code(fi.id, fi.span, fi.name, fi.node.descriptive_variant());
         }
         visit::walk_foreign_item(self, fi);
     }
@@ -544,7 +564,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
     fn visit_struct_field(&mut self, field: &hir::StructField) {
         if self.should_warn_about_field(&field.node) {
             self.warn_dead_code(field.node.id, field.span,
-                                field.node.ident().unwrap().name, "struct field");
+                                field.node.name().unwrap(), "struct field");
         }
 
         visit::walk_struct_field(self, field);
@@ -555,14 +575,14 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
             hir::ConstImplItem(_, ref expr) => {
                 if !self.symbol_is_live(impl_item.id, None) {
                     self.warn_dead_code(impl_item.id, impl_item.span,
-                                        impl_item.ident.name, "associated const");
+                                        impl_item.name, "associated const");
                 }
                 visit::walk_expr(self, expr)
             }
             hir::MethodImplItem(_, ref body) => {
                 if !self.symbol_is_live(impl_item.id, None) {
                     self.warn_dead_code(impl_item.id, impl_item.span,
-                                        impl_item.ident.name, "method");
+                                        impl_item.name, "method");
                 }
                 visit::walk_block(self, body)
             }
index 86133aad67216a0ee760e2918205e49319953998..ef2b918a9f5d7ea449f5e8df4d4d87a947822a85 100644 (file)
@@ -10,7 +10,7 @@
 
 pub use self::Def::*;
 
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::DefId;
 use middle::privacy::LastPrivate;
 use middle::subst::ParamSpace;
 use util::nodemap::NodeMap;
@@ -29,7 +29,8 @@ pub enum Def {
     DefStatic(DefId, bool /* is_mutbl */),
     DefConst(DefId),
     DefAssociatedConst(DefId),
-    DefLocal(ast::NodeId),
+    DefLocal(DefId, // def id of variable
+             ast::NodeId), // node id of variable
     DefVariant(DefId /* enum */, DefId /* variant */, bool /* is_structure */),
     DefTy(DefId, bool /* is_enum */),
     DefAssociatedTy(DefId /* trait */, DefId),
@@ -37,20 +38,20 @@ pub enum Def {
     DefPrimTy(hir::PrimTy),
     DefTyParam(ParamSpace, u32, DefId, ast::Name),
     DefUse(DefId),
-    DefUpvar(ast::NodeId,  // id of closed over local
+    DefUpvar(DefId,        // def id of closed over local
+             ast::NodeId,  // node id of closed over local
              usize,        // index in the freevars list of the closure
              ast::NodeId), // expr node that creates the closure
 
     /// Note that if it's a tuple struct's definition, the node id of the DefId
-    /// may either refer to the item definition's id or the StructDef.ctor_id.
+    /// may either refer to the item definition's id or the VariantData.ctor_id.
     ///
     /// The cases that I have encountered so far are (this is not exhaustive):
     /// - If it's a ty_path referring to some tuple struct, then DefMap maps
     ///   it to a def whose id is the item definition's id.
     /// - If it's an ExprPath referring to some tuple struct, then DefMap maps
-    ///   it to a def whose id is the StructDef.ctor_id.
+    ///   it to a def whose id is the VariantData.ctor_id.
     DefStruct(DefId),
-    DefRegion(ast::NodeId),
     DefLabel(ast::NodeId),
     DefMethod(DefId),
 }
@@ -114,10 +115,21 @@ pub struct Export {
 }
 
 impl Def {
-    pub fn local_node_id(&self) -> ast::NodeId {
-        let def_id = self.def_id();
-        assert_eq!(def_id.krate, LOCAL_CRATE);
-        def_id.node
+    pub fn var_id(&self) -> ast::NodeId {
+        match *self {
+            DefLocal(_, id) |
+            DefUpvar(_, id, _, _) => {
+                id
+            }
+
+            DefFn(..) | DefMod(..) | DefForeignMod(..) | DefStatic(..) |
+            DefVariant(..) | DefTy(..) | DefAssociatedTy(..) |
+            DefTyParam(..) | DefUse(..) | DefStruct(..) | DefTrait(..) |
+            DefMethod(..) | DefConst(..) | DefAssociatedConst(..) |
+            DefPrimTy(..) | DefLabel(..) | DefSelfTy(..) => {
+                panic!("attempted .def_id() on invalid {:?}", self)
+            }
+        }
     }
 
     pub fn def_id(&self) -> DefId {
@@ -126,19 +138,15 @@ impl Def {
             DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(_, id) |
             DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) |
             DefMethod(id) | DefConst(id) | DefAssociatedConst(id) |
-            DefSelfTy(Some(id), None)=> {
+            DefLocal(id, _) | DefUpvar(id, _, _, _) => {
                 id
             }
-            DefLocal(id) |
-            DefUpvar(id, _, _) |
-            DefRegion(id) |
-            DefLabel(id)  |
-            DefSelfTy(_, Some((_, id))) => {
-                DefId::local(id)
-            }
 
-            DefPrimTy(_) => panic!("attempted .def_id() on DefPrimTy"),
-            DefSelfTy(..) => panic!("attempted .def_id() on invalid DefSelfTy"),
+            DefLabel(..)  |
+            DefPrimTy(..) |
+            DefSelfTy(..) => {
+                panic!("attempted .def_id() on invalid def: {:?}", self)
+            }
         }
     }
 
index 2966339f0a4fff4f105de0523545a3856c007448..288eb01ebb4705d8aa58f2b66a66fb976312bb68 100644 (file)
@@ -8,31 +8,69 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use metadata::cstore::LOCAL_CRATE;
 use middle::ty;
-use syntax::ast::{CrateNum, NodeId};
+use syntax::ast::CrateNum;
 use std::fmt;
+use std::u32;
 
+/// A DefIndex is an index into the hir-map for a crate, identifying a
+/// particular definition. It should really be considered an interned
+/// shorthand for a particular DefPath.
+#[derive(Clone, Debug, Eq, Ord, PartialOrd, PartialEq, RustcEncodable,
+           RustcDecodable, Hash, Copy)]
+pub struct DefIndex(u32);
+
+impl DefIndex {
+    pub fn new(x: usize) -> DefIndex {
+        assert!(x < (u32::MAX as usize));
+        DefIndex(x as u32)
+    }
+
+    pub fn from_u32(x: u32) -> DefIndex {
+        DefIndex(x)
+    }
+
+    pub fn as_usize(&self) -> usize {
+        self.0 as usize
+    }
+
+    pub fn as_u32(&self) -> u32 {
+        self.0
+    }
+}
+
+/// The crate root is always assigned index 0 by the AST Map code,
+/// thanks to `NodeCollector::new`.
+pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0);
+
+/// A DefId identifies a particular *definition*, by combining a crate
+/// index and a def index.
 #[derive(Clone, Eq, Ord, PartialOrd, PartialEq, RustcEncodable,
            RustcDecodable, Hash, Copy)]
 pub struct DefId {
     pub krate: CrateNum,
-    pub node: NodeId,
+    pub index: DefIndex,
 }
 
 impl fmt::Debug for DefId {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "DefId {{ krate: {}, node: {}",
-                    self.krate, self.node));
+        try!(write!(f, "DefId {{ krate: {:?}, node: {:?}",
+                    self.krate, self.index));
 
         // Unfortunately, there seems to be no way to attempt to print
         // a path for a def-id, so I'll just make a best effort for now
         // and otherwise fallback to just printing the crate/node pair
-        try!(ty::tls::with_opt(|opt_tcx| {
-            if let Some(tcx) = opt_tcx {
-                try!(write!(f, " => {}", tcx.item_path_str(*self)));
-            }
-            Ok(())
-        }));
+        if self.is_local() { // (1)
+            // (1) side-step fact that not all external things have paths at
+            // the moment, such as type parameters
+            try!(ty::tls::with_opt(|opt_tcx| {
+                if let Some(tcx) = opt_tcx {
+                    try!(write!(f, " => {}", tcx.item_path_str(*self)));
+                }
+                Ok(())
+            }));
+        }
 
         write!(f, " }}")
     }
@@ -40,23 +78,11 @@ impl fmt::Debug for DefId {
 
 
 impl DefId {
-    pub fn local(id: NodeId) -> DefId {
-        DefId { krate: LOCAL_CRATE, node: id }
-    }
-
-    /// Read the node id, asserting that this def-id is krate-local.
-    pub fn local_id(&self) -> NodeId {
-        assert_eq!(self.krate, LOCAL_CRATE);
-        self.node
+    pub fn local(index: DefIndex) -> DefId {
+        DefId { krate: LOCAL_CRATE, index: index }
     }
 
     pub fn is_local(&self) -> bool {
         self.krate == LOCAL_CRATE
     }
 }
-
-
-/// Item definitions in the currently-compiled crate would have the CrateNum
-/// LOCAL_CRATE in their DefId.
-pub const LOCAL_CRATE: CrateNum = 0;
-
index d1e1434dad8ad94da9c95a7e2de1adcdc60e37b6..f849580871c845c563e836334c1e9c67b1a0c58f 100644 (file)
@@ -102,7 +102,6 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
     fn visit_block(&mut self, block: &hir::Block) {
         let old_unsafe_context = self.unsafe_context;
         match block.rules {
-            hir::DefaultBlock => {}
             hir::UnsafeBlock(source) => {
                 // By default only the outermost `unsafe` block is
                 // "used" and so nested unsafe blocks are pointless
@@ -131,6 +130,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
                 self.unsafe_context.push_unsafe_count =
                     self.unsafe_context.push_unsafe_count.checked_sub(1).unwrap();
             }
+            hir::DefaultBlock | hir::PushUnstableBlock | hir:: PopUnstableBlock => {}
         }
 
         visit::walk_block(self, block);
@@ -151,7 +151,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
                 }
             }
             hir::ExprCall(ref base, _) => {
-                let base_type = self.tcx.node_id_to_type(base.id);
+                let base_type = self.tcx.expr_ty_adjusted(base);
                 debug!("effect: call case, base type is {:?}",
                         base_type);
                 if type_is_unsafe_function(base_type) {
@@ -159,7 +159,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
                 }
             }
             hir::ExprUnary(hir::UnDeref, ref base) => {
-                let base_type = self.tcx.node_id_to_type(base.id);
+                let base_type = self.tcx.expr_ty_adjusted(base);
                 debug!("effect: unary case, base type is {:?}",
                         base_type);
                 if let ty::TyRawPtr(_) = base_type.sty {
index e32a9b280f3d517af2a38a6815d39e7c030903da..3cfcb52f9030fd6ac152e6f453639a202734b378 100644 (file)
 use front::map as ast_map;
 use session::{config, Session};
 use syntax::ast::NodeId;
-use rustc_front::hir::{Item, ItemFn};
-use rustc_front::attr;
+use syntax::attr;
 use syntax::codemap::Span;
 use syntax::entry::EntryPointType;
+use rustc_front::hir::{Item, ItemFn};
 use rustc_front::visit;
 use rustc_front::visit::Visitor;
 
@@ -85,7 +85,7 @@ fn entry_point_type(item: &Item, depth: usize) -> EntryPointType {
                 EntryPointType::Start
             } else if attr::contains_name(&item.attrs, "main") {
                 EntryPointType::MainAttr
-            } else if item.ident.name == "main" {
+            } else if item.name.as_str() == "main" {
                 if depth == 1 {
                     // This is a top-level function so can be 'main'
                     EntryPointType::MainNamed
index a8fed5eab16bef2d690c90f5ac9b3cd4d9b153ff..fb3a6b0f4202713ac303307d2a8e709d22fd3747 100644 (file)
@@ -244,7 +244,7 @@ impl OverloadedCallType {
 // can just use the tcx as the typer.
 //
 // FIXME(stage0): the :'t here is probably only important for stage0
-pub struct ExprUseVisitor<'d, 't, 'a: 't, 'tcx:'a+'d+'t> {
+pub struct ExprUseVisitor<'d, 't, 'a: 't, 'tcx:'a+'d> {
     typer: &'t infer::InferCtxt<'a, 'tcx>,
     mc: mc::MemCategorizationContext<'t, 'a, 'tcx>,
     delegate: &'d mut Delegate<'tcx>,
@@ -276,17 +276,13 @@ enum PassArgs {
 }
 
 impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
-    pub fn new(delegate: &'d mut Delegate<'tcx>,
+    pub fn new(delegate: &'d mut (Delegate<'tcx>),
                typer: &'t infer::InferCtxt<'a, 'tcx>)
-               -> ExprUseVisitor<'d,'t,'a,'tcx>
+               -> ExprUseVisitor<'d,'t,'a,'tcx> where 'tcx:'a+'d
     {
-        let result = ExprUseVisitor {
-            typer: typer,
-            mc: mc::MemCategorizationContext::new(typer),
-            delegate: delegate,
-        };
-
-        result
+        let mc: mc::MemCategorizationContext<'t, 'a, 'tcx> =
+            mc::MemCategorizationContext::new(typer);
+        ExprUseVisitor { typer: typer, mc: mc, delegate: delegate }
     }
 
     pub fn walk_fn(&mut self,
@@ -362,9 +358,6 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         let cmt = return_if_err!(self.mc.cat_expr(expr));
         self.delegate.borrow(expr.id, expr.span, cmt, r, bk, cause);
 
-        // Note: Unlike consume, we can ignore ExprParen. cat_expr
-        // already skips over them, and walk will uncover any
-        // attachments or whatever.
         self.walk_expr(expr)
     }
 
@@ -378,10 +371,6 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         self.walk_adjustment(expr);
 
         match expr.node {
-            hir::ExprParen(ref subexpr) => {
-                self.walk_expr(&**subexpr)
-            }
-
             hir::ExprPath(..) => { }
 
             hir::ExprUnary(hir::UnDeref, ref base) => {      // *base
@@ -532,11 +521,14 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                 self.consume_expr(&**base);
             }
 
-            hir::ExprAssignOp(_, ref lhs, ref rhs) => {
-                // This will have to change if/when we support
-                // overloaded operators for `+=` and so forth.
-                self.mutate_expr(expr, &**lhs, WriteAndRead);
-                self.consume_expr(&**rhs);
+            hir::ExprAssignOp(op, ref lhs, ref rhs) => {
+                // NB All our assignment operations take the RHS by value
+                assert!(::rustc_front::util::is_by_value_binop(op.node));
+
+                if !self.walk_overloaded_operator(expr, lhs, vec![rhs], PassArgs::ByValue) {
+                    self.mutate_expr(expr, &**lhs, WriteAndRead);
+                    self.consume_expr(&**rhs);
+                }
             }
 
             hir::ExprRepeat(ref base, ref count) => {
@@ -548,17 +540,8 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                 self.walk_captures(expr)
             }
 
-            hir::ExprBox(ref place, ref base) => {
-                match *place {
-                    Some(ref place) => self.consume_expr(&**place),
-                    None => {}
-                }
+            hir::ExprBox(ref base) => {
                 self.consume_expr(&**base);
-                if place.is_some() {
-                    self.tcx().sess.span_bug(
-                        expr.span,
-                        "box with explicit place remains after expansion");
-                }
             }
         }
     }
@@ -714,7 +697,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                                 -> bool
         {
             fields.iter().any(
-                |f| f.ident.node.name == field.name)
+                |f| f.name.node == field.name)
         }
     }
 
@@ -930,7 +913,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         self.consume_expr(&*arm.body);
     }
 
-    /// Walks an pat that occurs in isolation (i.e. top-level of fn
+    /// Walks a pat that occurs in isolation (i.e. top-level of fn
     /// arg or let binding.  *Not* a match arm or nested pat.)
     fn walk_irrefutable_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat) {
         let mut mode = Unknown;
@@ -1153,7 +1136,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                 }
 
                 hir::PatIdent(_, _, Some(_)) => {
-                    // Do nothing; this is a binding (not a enum
+                    // Do nothing; this is a binding (not an enum
                     // variant or struct), and the cat_pattern call
                     // will visit the substructure recursively.
                 }
@@ -1162,7 +1145,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                 hir::PatRegion(..) | hir::PatLit(..) | hir::PatRange(..) |
                 hir::PatVec(..) => {
                     // Similarly, each of these cases does not
-                    // correspond to a enum variant or struct, so we
+                    // correspond to an enum variant or struct, so we
                     // do not do any `matched_pat` calls for these
                     // cases either.
                 }
@@ -1175,7 +1158,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
 
         self.tcx().with_freevars(closure_expr.id, |freevars| {
             for freevar in freevars {
-                let id_var = freevar.def.def_id().node;
+                let id_var = freevar.def.var_id();
                 let upvar_id = ty::UpvarId { var_id: id_var,
                                              closure_expr_id: closure_expr.id };
                 let upvar_capture = self.typer.upvar_capture(upvar_id).unwrap();
@@ -1207,7 +1190,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                         -> mc::McResult<mc::cmt<'tcx>> {
         // Create the cmt for the variable being borrowed, from the
         // caller's perspective
-        let var_id = upvar_def.def_id().node;
+        let var_id = upvar_def.var_id();
         let var_ty = try!(self.typer.node_ty(var_id));
         self.mc.cat_def(closure_id, closure_span, var_ty, upvar_def)
     }
index 2e9e5fafb1d9b348dce9a2afb58aa48d37422160..face6d629340db1aaf6aef013984b1f38828c870 100644 (file)
@@ -10,7 +10,7 @@
 
 //! This file handles the relationships between free regions --
 //! meaning lifetime parameters. Ordinarily, free regions are
-//! unrelated to one another, but they can be related vai implied or
+//! unrelated to one another, but they can be related via implied or
 //! explicit bounds.  In that case, we track the bounds using the
 //! `TransitiveRelation` type and use that to decide when one free
 //! region outlives another and so forth.
index 2447a8cee7bbb9d56bf9c0e1d2f8969a350e04f1..03554a59655b162c4ef18e7819333a0e2cd7d7bf 100644 (file)
@@ -48,8 +48,8 @@ use middle::ty::error::TypeError;
 use middle::ty::fold::{TypeFolder, TypeFoldable};
 use middle::ty::relate::{Relate, RelateResult, TypeRelation};
 
+use syntax::ast;
 use syntax::codemap::Span;
-use rustc_front::hir;
 
 #[derive(Clone)]
 pub struct CombineFields<'a, 'tcx: 'a> {
@@ -138,7 +138,7 @@ fn unify_integral_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
 fn unify_float_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
                                  vid_is_expected: bool,
                                  vid: ty::FloatVid,
-                                 val: hir::FloatTy)
+                                 val: ast::FloatTy)
                                  -> RelateResult<'tcx, Ty<'tcx>>
 {
     try!(infcx
@@ -388,7 +388,7 @@ fn int_unification_error<'tcx>(a_is_expected: bool, v: (ty::IntVarValue, ty::Int
 }
 
 fn float_unification_error<'tcx>(a_is_expected: bool,
-                                 v: (hir::FloatTy, hir::FloatTy))
+                                 v: (ast::FloatTy, ast::FloatTy))
                                  -> TypeError<'tcx>
 {
     let (a, b) = v;
index 07ce4688c069f1ec9e46f7ea5ac0ca965580a78b..d1dad4921ae2107cdc9d545c80a066eda3dc9078 100644 (file)
@@ -17,6 +17,7 @@ use middle::ty::{self, Ty};
 use middle::ty::TyVar;
 use middle::ty::relate::{Relate, RelateResult, TypeRelation};
 
+/// Ensures `a` is made equal to `b`. Returns `a` on success.
 pub struct Equate<'a, 'tcx: 'a> {
     fields: CombineFields<'a, 'tcx>
 }
@@ -68,7 +69,8 @@ impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> {
             }
 
             _ => {
-                combine::super_combine_tys(self.fields.infcx, self, a, b)
+                try!(combine::super_combine_tys(self.fields.infcx, self, a, b));
+                Ok(a)
             }
         }
     }
index f0fa7d7cdf851b0f5a12bfbeb6a5423e5fc3de9e..880e181cdef143750f712193123261146af5a1cf 100644 (file)
@@ -65,7 +65,6 @@ use super::ValuePairs;
 use super::region_inference::RegionResolutionError;
 use super::region_inference::ConcreteFailure;
 use super::region_inference::SubSupConflict;
-use super::region_inference::SupSupConflict;
 use super::region_inference::GenericBoundFailure;
 use super::region_inference::GenericKind;
 use super::region_inference::ProcessedErrors;
@@ -258,13 +257,6 @@ pub trait ErrorReporting<'tcx> {
                                sup_origin: SubregionOrigin<'tcx>,
                                sup_region: Region);
 
-    fn report_sup_sup_conflict(&self,
-                               var_origin: RegionVariableOrigin,
-                               origin1: SubregionOrigin<'tcx>,
-                               region1: Region,
-                               origin2: SubregionOrigin<'tcx>,
-                               region2: Region);
-
     fn report_processed_errors(&self,
                                var_origin: &[RegionVariableOrigin],
                                trace_origin: &[(TypeTrace<'tcx>, TypeError<'tcx>)],
@@ -284,7 +276,7 @@ trait ErrorReportingHelpers<'tcx> {
                                 decl: &hir::FnDecl,
                                 unsafety: hir::Unsafety,
                                 constness: hir::Constness,
-                                ident: ast::Ident,
+                                name: ast::Name,
                                 opt_explicit_self: Option<&hir::ExplicitSelf_>,
                                 generics: &hir::Generics,
                                 span: Span);
@@ -313,14 +305,6 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                                                  sup_origin, sup_r);
                 }
 
-                SupSupConflict(var_origin,
-                               origin1, r1,
-                               origin2, r2) => {
-                    self.report_sup_sup_conflict(var_origin,
-                                                 origin1, r1,
-                                                 origin2, r2);
-                }
-
                 ProcessedErrors(ref var_origins,
                                 ref trace_origins,
                                 ref same_regions) => {
@@ -376,7 +360,6 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                         None => processed_errors.push((*error).clone()),
                     }
                 }
-                SupSupConflict(..) => processed_errors.push((*error).clone()),
                 _ => ()  // This shouldn't happen
             }
         }
@@ -718,20 +701,17 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     "");
             }
             infer::DerefPointer(span) => {
-                self.tcx.sess.span_err(
-                    span,
-                    "dereference of reference outside its lifetime");
+                span_err!(self.tcx.sess, span, E0473,
+                          "dereference of reference outside its lifetime");
                 self.tcx.note_and_explain_region(
                     "the reference is only valid for ",
                     sup,
                     "");
             }
             infer::FreeVariable(span, id) => {
-                self.tcx.sess.span_err(
-                    span,
-                    &format!("captured variable `{}` does not \
-                              outlive the enclosing closure",
-                             self.tcx.local_var_name_str(id)));
+                span_err!(self.tcx.sess, span, E0474,
+                          "captured variable `{}` does not outlive the enclosing closure",
+                          self.tcx.local_var_name_str(id));
                 self.tcx.note_and_explain_region(
                     "captured variable is valid for ",
                     sup,
@@ -742,18 +722,17 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     "");
             }
             infer::IndexSlice(span) => {
-                self.tcx.sess.span_err(span,
-                                       "index of slice outside its lifetime");
+                span_err!(self.tcx.sess, span, E0475,
+                          "index of slice outside its lifetime");
                 self.tcx.note_and_explain_region(
                     "the slice is only valid for ",
                     sup,
                     "");
             }
             infer::RelateObjectBound(span) => {
-                self.tcx.sess.span_err(
-                    span,
-                    "lifetime of the source pointer does not outlive \
-                     lifetime bound of the object type");
+                span_err!(self.tcx.sess, span, E0476,
+                          "lifetime of the source pointer does not outlive \
+                           lifetime bound of the object type");
                 self.tcx.note_and_explain_region(
                     "object type is valid for ",
                     sub,
@@ -764,20 +743,17 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     "");
             }
             infer::RelateParamBound(span, ty) => {
-                self.tcx.sess.span_err(
-                    span,
-                    &format!("the type `{}` does not fulfill the \
-                             required lifetime",
-                            self.ty_to_string(ty)));
+                span_err!(self.tcx.sess, span, E0477,
+                          "the type `{}` does not fulfill the required lifetime",
+                          self.ty_to_string(ty));
                 self.tcx.note_and_explain_region(
                                         "type must outlive ",
                                         sub,
                                         "");
             }
             infer::RelateRegionParamBound(span) => {
-                self.tcx.sess.span_err(
-                    span,
-                    "lifetime bound not satisfied");
+                span_err!(self.tcx.sess, span, E0478,
+                          "lifetime bound not satisfied");
                 self.tcx.note_and_explain_region(
                     "lifetime parameter instantiated with ",
                     sup,
@@ -788,92 +764,82 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     "");
             }
             infer::RelateDefaultParamBound(span, ty) => {
-                self.tcx.sess.span_err(
-                    span,
-                    &format!("the type `{}` (provided as the value of \
-                             a type parameter) is not valid at this point",
-                            self.ty_to_string(ty)));
+                span_err!(self.tcx.sess, span, E0479,
+                          "the type `{}` (provided as the value of \
+                           a type parameter) is not valid at this point",
+                          self.ty_to_string(ty));
                 self.tcx.note_and_explain_region(
                                         "type must outlive ",
                                         sub,
                                         "");
             }
             infer::CallRcvr(span) => {
-                self.tcx.sess.span_err(
-                    span,
-                    "lifetime of method receiver does not outlive \
-                     the method call");
+                span_err!(self.tcx.sess, span, E0480,
+                          "lifetime of method receiver does not outlive \
+                           the method call");
                 self.tcx.note_and_explain_region(
                     "the receiver is only valid for ",
                     sup,
                     "");
             }
             infer::CallArg(span) => {
-                self.tcx.sess.span_err(
-                    span,
-                    "lifetime of function argument does not outlive \
-                     the function call");
+                span_err!(self.tcx.sess, span, E0481,
+                          "lifetime of function argument does not outlive \
+                           the function call");
                 self.tcx.note_and_explain_region(
                     "the function argument is only valid for ",
                     sup,
                     "");
             }
             infer::CallReturn(span) => {
-                self.tcx.sess.span_err(
-                    span,
-                    "lifetime of return value does not outlive \
-                     the function call");
+                span_err!(self.tcx.sess, span, E0482,
+                          "lifetime of return value does not outlive \
+                           the function call");
                 self.tcx.note_and_explain_region(
                     "the return value is only valid for ",
                     sup,
                     "");
             }
             infer::Operand(span) => {
-                self.tcx.sess.span_err(
-                    span,
-                    "lifetime of operand does not outlive \
-                     the operation");
+                span_err!(self.tcx.sess, span, E0483,
+                          "lifetime of operand does not outlive \
+                           the operation");
                 self.tcx.note_and_explain_region(
                     "the operand is only valid for ",
                     sup,
                     "");
             }
             infer::AddrOf(span) => {
-                self.tcx.sess.span_err(
-                    span,
-                    "reference is not valid \
-                     at the time of borrow");
+                span_err!(self.tcx.sess, span, E0484,
+                          "reference is not valid at the time of borrow");
                 self.tcx.note_and_explain_region(
                     "the borrow is only valid for ",
                     sup,
                     "");
             }
             infer::AutoBorrow(span) => {
-                self.tcx.sess.span_err(
-                    span,
-                    "automatically reference is not valid \
-                     at the time of borrow");
+                span_err!(self.tcx.sess, span, E0485,
+                          "automatically reference is not valid \
+                           at the time of borrow");
                 self.tcx.note_and_explain_region(
                     "the automatic borrow is only valid for ",
                     sup,
                     "");
             }
             infer::ExprTypeIsNotInScope(t, span) => {
-                self.tcx.sess.span_err(
-                    span,
-                    &format!("type of expression contains references \
-                             that are not valid during the expression: `{}`",
-                            self.ty_to_string(t)));
+                span_err!(self.tcx.sess, span, E0486,
+                          "type of expression contains references \
+                           that are not valid during the expression: `{}`",
+                          self.ty_to_string(t));
                 self.tcx.note_and_explain_region(
                     "type is only valid for ",
                     sup,
                     "");
             }
             infer::SafeDestructor(span) => {
-                self.tcx.sess.span_err(
-                    span,
-                    "unsafe use of destructor: destructor might be called \
-                     while references are dead");
+                span_err!(self.tcx.sess, span, E0487,
+                          "unsafe use of destructor: destructor might be called \
+                           while references are dead");
                 // FIXME (22171): terms "super/subregion" are suboptimal
                 self.tcx.note_and_explain_region(
                     "superregion: ",
@@ -885,37 +851,33 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     "");
             }
             infer::BindingTypeIsNotValidAtDecl(span) => {
-                self.tcx.sess.span_err(
-                    span,
-                    "lifetime of variable does not enclose its declaration");
+                span_err!(self.tcx.sess, span, E0488,
+                          "lifetime of variable does not enclose its declaration");
                 self.tcx.note_and_explain_region(
                     "the variable is only valid for ",
                     sup,
                     "");
             }
             infer::ParameterInScope(_, span) => {
-                self.tcx.sess.span_err(
-                    span,
-                    &format!("type/lifetime parameter not in scope here"));
+                span_err!(self.tcx.sess, span, E0489,
+                          "type/lifetime parameter not in scope here");
                 self.tcx.note_and_explain_region(
                     "the parameter is only valid for ",
                     sub,
                     "");
             }
             infer::DataBorrowed(ty, span) => {
-                self.tcx.sess.span_err(
-                    span,
-                    &format!("a value of type `{}` is borrowed for too long",
-                             self.ty_to_string(ty)));
+                span_err!(self.tcx.sess, span, E0490,
+                          "a value of type `{}` is borrowed for too long",
+                          self.ty_to_string(ty));
                 self.tcx.note_and_explain_region("the type is valid for ", sub, "");
                 self.tcx.note_and_explain_region("but the borrow lasts for ", sup, "");
             }
             infer::ReferenceOutlivesReferent(ty, span) => {
-                self.tcx.sess.span_err(
-                    span,
-                    &format!("in type `{}`, reference has a longer lifetime \
-                             than the data it references",
-                            self.ty_to_string(ty)));
+                span_err!(self.tcx.sess, span, E0491,
+                          "in type `{}`, reference has a longer lifetime \
+                           than the data it references",
+                          self.ty_to_string(ty));
                 self.tcx.note_and_explain_region(
                     "the pointer is valid for ",
                     sub,
@@ -951,29 +913,6 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
         self.note_region_origin(&sub_origin);
     }
 
-    fn report_sup_sup_conflict(&self,
-                               var_origin: RegionVariableOrigin,
-                               origin1: SubregionOrigin<'tcx>,
-                               region1: Region,
-                               origin2: SubregionOrigin<'tcx>,
-                               region2: Region) {
-        self.report_inference_failure(var_origin);
-
-        self.tcx.note_and_explain_region(
-            "first, the lifetime must be contained by ",
-            region1,
-            "...");
-
-        self.note_region_origin(&origin1);
-
-        self.tcx.note_and_explain_region(
-            "but, the lifetime must also be contained by ",
-            region2,
-            "...");
-
-        self.note_region_origin(&origin2);
-    }
-
     fn report_processed_errors(&self,
                                var_origins: &[RegionVariableOrigin],
                                trace_origins: &[(TypeTrace<'tcx>, TypeError<'tcx>)],
@@ -999,7 +938,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     match item.node {
                         hir::ItemFn(ref fn_decl, unsafety, constness, _, ref gen, _) => {
                             Some((fn_decl, gen, unsafety, constness,
-                                  item.ident, None, item.span))
+                                  item.name, None, item.span))
                         },
                         _ => None
                     }
@@ -1011,7 +950,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                                   &sig.generics,
                                   sig.unsafety,
                                   sig.constness,
-                                  item.ident,
+                                  item.name,
                                   Some(&sig.explicit_self.node),
                                   item.span))
                         }
@@ -1025,7 +964,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                                   &sig.generics,
                                   sig.unsafety,
                                   sig.constness,
-                                  item.ident,
+                                  item.name,
                                   Some(&sig.explicit_self.node),
                                   item.span))
                         }
@@ -1036,12 +975,12 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
             },
             None => None
         };
-        let (fn_decl, generics, unsafety, constness, ident, expl_self, span)
+        let (fn_decl, generics, unsafety, constness, name, expl_self, span)
                                     = node_inner.expect("expect item fn");
         let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self,
                                        generics, same_regions, &life_giver);
         let (fn_decl, expl_self, generics) = rebuilder.rebuild();
-        self.give_expl_lifetime_param(&fn_decl, unsafety, constness, ident,
+        self.give_expl_lifetime_param(&fn_decl, unsafety, constness, name,
                                       expl_self.as_ref(), &generics, span);
     }
 }
@@ -1148,7 +1087,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                 names.push(lt_name);
             }
             names.sort();
-            let name = token::str_to_ident(&names[0]).name;
+            let name = token::intern(&names[0]);
             return (name_to_dummy_lifetime(name), Kept);
         }
         return (self.life_giver.give_lifetime(), Fresh);
@@ -1219,7 +1158,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                                                       lifetime,
                                                       region_names);
             hir::TyParam {
-                ident: ty_param.ident,
+                name: ty_param.name,
                 id: ty_param.id,
                 bounds: bounds,
                 default: ty_param.default.clone(),
@@ -1562,7 +1501,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                 let new_bindings = data.bindings.map(|b| {
                     P(hir::TypeBinding {
                         id: b.id,
-                        ident: b.ident,
+                        name: b.name,
                         ty: self.rebuild_arg_ty_or_output(&*b.ty,
                                                           lifetime,
                                                           anon_nums,
@@ -1597,11 +1536,11 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
                                 decl: &hir::FnDecl,
                                 unsafety: hir::Unsafety,
                                 constness: hir::Constness,
-                                ident: ast::Ident,
+                                name: ast::Name,
                                 opt_explicit_self: Option<&hir::ExplicitSelf_>,
                                 generics: &hir::Generics,
                                 span: Span) {
-        let suggested_fn = pprust::fun_to_string(decl, unsafety, constness, ident,
+        let suggested_fn = pprust::fun_to_string(decl, unsafety, constness, name,
                                                  opt_explicit_self, generics);
         let msg = format!("consider using an explicit lifetime \
                            parameter as shown: {}", suggested_fn);
@@ -1648,11 +1587,10 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
             }
         };
 
-        self.tcx.sess.span_err(
-            var_origin.span(),
-            &format!("cannot infer an appropriate lifetime{} \
-                    due to conflicting requirements",
-                    var_description));
+        span_err!(self.tcx.sess, var_origin.span(), E0495,
+                  "cannot infer an appropriate lifetime{} \
+                   due to conflicting requirements",
+                  var_description);
     }
 
     fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
@@ -1779,7 +1717,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
                     "...so that return value is valid for the call");
             }
             infer::Operand(span) => {
-                self.tcx.sess.span_err(
+                self.tcx.sess.span_note(
                     span,
                     "...so that operand is valid for operation");
             }
@@ -1960,8 +1898,7 @@ impl LifeGiver {
             let mut s = String::from("'");
             s.push_str(&num_to_string(self.counter.get()));
             if !self.taken.contains(&s) {
-                lifetime = name_to_dummy_lifetime(
-                                    token::str_to_ident(&s[..]).name);
+                lifetime = name_to_dummy_lifetime(token::intern(&s[..]));
                 self.generated.borrow_mut().push(lifetime);
                 break;
             }
index b0fce71d3f06143523856dacc51e85acd62164e0..ef6d9ae41914b00e84755e1450300b09eb486d42 100644 (file)
@@ -567,7 +567,7 @@ pub fn plug_leaks<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
 
     // Compute a mapping from the "taint set" of each skolemized
     // region back to the `ty::BoundRegion` that it originally
-    // represented. Because `leak_check` passed, we know that that
+    // represented. Because `leak_check` passed, we know that
     // these taint sets are mutually disjoint.
     let inv_skol_map: FnvHashMap<ty::Region, ty::BoundRegion> =
         skol_map
index 0c1c905c8dadbd5dd7db569a1d31b8a540dcbbed..84673b010332fa90f0bdb80e6fe71e13444e9391 100644 (file)
@@ -1462,7 +1462,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                         def_id: DefId)
                         -> Option<ty::ClosureKind>
     {
-        self.tables.borrow().closure_kinds.get(&def_id).cloned()
+        if def_id.is_local() {
+            self.tables.borrow().closure_kinds.get(&def_id).cloned()
+        } else {
+            // During typeck, ALL closures are local. But afterwards,
+            // during trans, we see closure ids from other traits.
+            // That may require loading the closure data out of the
+            // cstore.
+            Some(ty::Tables::closure_kind(&self.tables, self.tcx, def_id))
+        }
     }
 
     pub fn closure_type(&self,
@@ -1470,12 +1478,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                         substs: &ty::ClosureSubsts<'tcx>)
                         -> ty::ClosureTy<'tcx>
     {
-        let closure_ty = self.tables
-                             .borrow()
-                             .closure_tys
-                             .get(&def_id)
-                             .unwrap()
-                             .subst(self.tcx, &substs.func_substs);
+        let closure_ty =
+            ty::Tables::closure_type(self.tables,
+                                     self.tcx,
+                                     def_id,
+                                     substs);
 
         if self.normalize {
             normalize_associated_type(&self.tcx, &closure_ty)
index 2dc16d4fa1dd419e0edacba3142cb00847adebe4..80da861139b42fd9acc50f686746219a5f091c4a 100644 (file)
@@ -2,13 +2,12 @@ Region inference
 
 # Terminology
 
-Note that we use the terms region and lifetime interchangeably,
-though the term `lifetime` is preferred.
+Note that we use the terms region and lifetime interchangeably.
 
 # Introduction
 
 Region inference uses a somewhat more involved algorithm than type
-inference.  It is not the most efficient thing ever written though it
+inference. It is not the most efficient thing ever written though it
 seems to work well enough in practice (famous last words).  The reason
 that we use a different algorithm is because, unlike with types, it is
 impractical to hand-annotate with regions (in some cases, there aren't
@@ -25,22 +24,42 @@ once.
 
 The constraints are always of one of three possible forms:
 
-- ConstrainVarSubVar(R_i, R_j) states that region variable R_i
-  must be a subregion of R_j
-- ConstrainRegSubVar(R, R_i) states that the concrete region R
-  (which must not be a variable) must be a subregion of the variable R_i
-- ConstrainVarSubReg(R_i, R) is the inverse
+- `ConstrainVarSubVar(Ri, Rj)` states that region variable Ri must be
+  a subregion of Rj
+- `ConstrainRegSubVar(R, Ri)` states that the concrete region R (which
+  must not be a variable) must be a subregion of the variable Ri
+- `ConstrainVarSubReg(Ri, R)` states the variable Ri shoudl be less
+  than the concrete region R. This is kind of deprecated and ought to
+  be replaced with a verify (they essentially play the same role).
+
+In addition to constraints, we also gather up a set of "verifys"
+(what, you don't think Verify is a noun? Get used to it my
+friend!). These represent relations that must hold but which don't
+influence inference proper. These take the form of:
+
+- `VerifyRegSubReg(Ri, Rj)` indicates that Ri <= Rj must hold,
+  where Rj is not an inference variable (and Ri may or may not contain
+  one). This doesn't influence inference because we will already have
+  inferred Ri to be as small as possible, so then we just test whether
+  that result was less than Rj or not.
+- `VerifyGenericBound(R, Vb)` is a more complex expression which tests
+  that the region R must satisfy the bound `Vb`. The bounds themselves
+  may have structure like "must outlive one of the following regions"
+  or "must outlive ALL of the following regions. These bounds arise
+  from constraints like `T: 'a` -- if we know that `T: 'b` and `T: 'c`
+  (say, from where clauses), then we can conclude that `T: 'a` if `'b:
+  'a` *or* `'c: 'a`.
 
 # Building up the constraints
 
 Variables and constraints are created using the following methods:
 
 - `new_region_var()` creates a new, unconstrained region variable;
-- `make_subregion(R_i, R_j)` states that R_i is a subregion of R_j
-- `lub_regions(R_i, R_j) -> R_k` returns a region R_k which is
-  the smallest region that is greater than both R_i and R_j
-- `glb_regions(R_i, R_j) -> R_k` returns a region R_k which is
-  the greatest region that is smaller than both R_i and R_j
+- `make_subregion(Ri, Rj)` states that Ri is a subregion of Rj
+- `lub_regions(Ri, Rj) -> Rk` returns a region Rk which is
+  the smallest region that is greater than both Ri and Rj
+- `glb_regions(Ri, Rj) -> Rk` returns a region Rk which is
+  the greatest region that is smaller than both Ri and Rj
 
 The actual region resolution algorithm is not entirely
 obvious, though it is also not overly complex.
@@ -54,14 +73,6 @@ Alternatively, you can call `commit()` which ends all snapshots.
 Snapshots can be recursive---so you can start a snapshot when another
 is in progress, but only the root snapshot can "commit".
 
-# Resolving constraints
-
-The constraint resolution algorithm is not super complex but also not
-entirely obvious.  Here I describe the problem somewhat abstractly,
-then describe how the current code works.  There may be other, smarter
-ways of doing this with which I am unfamiliar and can't be bothered to
-research at the moment. - NDM
-
 ## The problem
 
 Basically our input is a directed graph where nodes can be divided
@@ -83,31 +94,20 @@ Before resolution begins, we build up the constraints in a hashmap
 that maps `Constraint` keys to spans.  During resolution, we construct
 the actual `Graph` structure that we describe here.
 
-## Our current algorithm
-
-We divide region variables into two groups: Expanding and Contracting.
-Expanding region variables are those that have a concrete region
-predecessor (direct or indirect).  Contracting region variables are
-all others.
-
-We first resolve the values of Expanding region variables and then
-process Contracting ones.  We currently use an iterative, fixed-point
-procedure (but read on, I believe this could be replaced with a linear
-walk).  Basically we iterate over the edges in the graph, ensuring
-that, if the source of the edge has a value, then this value is a
-subregion of the target value.  If the target does not yet have a
-value, it takes the value from the source.  If the target already had
-a value, then the resulting value is Least Upper Bound of the old and
-new values. When we are done, each Expanding node will have the
-smallest region that it could possibly have and still satisfy the
-constraints.
-
-We next process the Contracting nodes.  Here we again iterate over the
-edges, only this time we move values from target to source (if the
-source is a Contracting node).  For each contracting node, we compute
-its value as the GLB of all its successors.  Basically contracting
-nodes ensure that there is overlap between their successors; we will
-ultimately infer the largest overlap possible.
+## Computing the values for region variables
+
+The algorithm is a simple dataflow algorithm. Each region variable
+begins as empty. We iterate over the constraints, and for each constraint
+we grow the relevant region variable to be as big as it must be to meet all the
+constraints. This means the region variables can grow to be `'static` if
+necessary.
+
+## Verification
+
+After all constraints are fully propoagated, we do a "verification"
+step where we walk over the verify bounds and check that they are
+satisfied. These bounds represent the "maximal" values that a region
+variable can take on, basically.
 
 # The Region Hierarchy
 
index 1fc5294877065efc2bffd945ff534fb2941ee3e7..279ab9d5f30b2ff3765dc984449def282afed985 100644 (file)
@@ -16,19 +16,16 @@ pub use self::UndoLogEntry::*;
 pub use self::CombineMapType::*;
 pub use self::RegionResolutionError::*;
 pub use self::VarValue::*;
-use self::Classification::*;
 
 use super::{RegionVariableOrigin, SubregionOrigin, TypeTrace, MiscVariable};
 
 use rustc_data_structures::graph::{self, Direction, NodeIndex};
 use middle::free_region::FreeRegionMap;
-use middle::region;
 use middle::ty::{self, Ty};
 use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid};
 use middle::ty::{ReEmpty, ReStatic, ReFree, ReEarlyBound};
 use middle::ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
 use middle::ty::error::TypeError;
-use middle::ty::relate::RelateResult;
 use util::common::indenter;
 use util::nodemap::{FnvHashMap, FnvHashSet};
 
@@ -50,6 +47,8 @@ pub enum Constraint {
     ConstrainRegSubVar(Region, RegionVid),
 
     // Region variable is subregion of concrete region
+    //
+    // FIXME(#29436) -- should be remove in favor of a Verify
     ConstrainVarSubReg(RegionVid, Region),
 }
 
@@ -144,15 +143,6 @@ pub enum RegionResolutionError<'tcx> {
                    SubregionOrigin<'tcx>, Region,
                    SubregionOrigin<'tcx>, Region),
 
-    /// `SupSupConflict(v, origin1, r1, origin2, r2)`:
-    ///
-    /// Could not infer a value for `v` because `v <= r1` (due to
-    /// `origin1`) and `v <= r2` (due to `origin2`) and
-    /// `r1` and `r2` have no intersection.
-    SupSupConflict(RegionVariableOrigin,
-                   SubregionOrigin<'tcx>, Region,
-                   SubregionOrigin<'tcx>, Region),
-
     /// For subsets of `ConcreteFailure` and `SubSupConflict`, we can derive
     /// more specific errors message by suggesting to the user where they
     /// should put a lifetime. In those cases we process and put those errors
@@ -824,147 +814,14 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
           }
         }
     }
-
-    fn glb_concrete_regions(&self,
-                            free_regions: &FreeRegionMap,
-                            a: Region,
-                            b: Region)
-                            -> RelateResult<'tcx, Region>
-    {
-        debug!("glb_concrete_regions({:?}, {:?})", a, b);
-        match (a, b) {
-            (ReLateBound(..), _) |
-            (_, ReLateBound(..)) |
-            (ReEarlyBound(..), _) |
-            (_, ReEarlyBound(..)) => {
-              self.tcx.sess.bug(
-                  &format!("cannot relate bound region: GLB({:?}, {:?})",
-                          a,
-                          b));
-            }
-
-            (ReStatic, r) | (r, ReStatic) => {
-                // static lives longer than everything else
-                Ok(r)
-            }
-
-            (ReEmpty, _) | (_, ReEmpty) => {
-                // nothing lives shorter than everything else
-                Ok(ReEmpty)
-            }
-
-            (ReVar(v_id), _) |
-            (_, ReVar(v_id)) => {
-                self.tcx.sess.span_bug(
-                    (*self.var_origins.borrow())[v_id.index as usize].span(),
-                    &format!("glb_concrete_regions invoked with \
-                             non-concrete regions: {:?}, {:?}",
-                            a,
-                            b));
-            }
-
-            (ReFree(fr), ReScope(s_id)) |
-            (ReScope(s_id), ReFree(fr)) => {
-                let s = ReScope(s_id);
-                // Free region is something "at least as big as
-                // `fr.scope_id`."  If we find that the scope `fr.scope_id` is bigger
-                // than the scope `s_id`, then we can say that the GLB
-                // is the scope `s_id`.  Otherwise, as we do not know
-                // big the free region is precisely, the GLB is undefined.
-                if self.tcx.region_maps.nearest_common_ancestor(fr.scope, s_id) == fr.scope ||
-                        free_regions.is_static(fr) {
-                    Ok(s)
-                } else {
-                    Err(TypeError::RegionsNoOverlap(b, a))
-                }
-            }
-
-            (ReScope(a_id), ReScope(b_id)) => {
-                self.intersect_scopes(a, b, a_id, b_id)
-            }
-
-            (ReFree(ref a_fr), ReFree(ref b_fr)) => {
-                self.glb_free_regions(free_regions, a_fr, b_fr)
-            }
-
-            // For these types, we cannot define any additional
-            // relationship:
-            (ReSkolemized(..), _) |
-            (_, ReSkolemized(..)) => {
-                if a == b {
-                    Ok(a)
-                } else {
-                    Err(TypeError::RegionsNoOverlap(b, a))
-                }
-            }
-        }
-    }
-
-    /// Computes a region that is enclosed by both free region arguments, if any. Guarantees that
-    /// if the same two regions are given as argument, in any order, a consistent result is
-    /// returned.
-    fn glb_free_regions(&self,
-                        free_regions: &FreeRegionMap,
-                        a: &FreeRegion,
-                        b: &FreeRegion)
-                        -> RelateResult<'tcx, ty::Region>
-    {
-        return match a.cmp(b) {
-            Less => helper(self, free_regions, a, b),
-            Greater => helper(self, free_regions, b, a),
-            Equal => Ok(ty::ReFree(*a))
-        };
-
-        fn helper<'a, 'tcx>(this: &RegionVarBindings<'a, 'tcx>,
-                            free_regions: &FreeRegionMap,
-                            a: &FreeRegion,
-                            b: &FreeRegion) -> RelateResult<'tcx, ty::Region>
-        {
-            if free_regions.sub_free_region(*a, *b) {
-                Ok(ty::ReFree(*a))
-            } else if free_regions.sub_free_region(*b, *a) {
-                Ok(ty::ReFree(*b))
-            } else {
-                this.intersect_scopes(ty::ReFree(*a), ty::ReFree(*b),
-                                      a.scope, b.scope)
-            }
-        }
-    }
-
-    fn intersect_scopes(&self,
-                        region_a: ty::Region,
-                        region_b: ty::Region,
-                        scope_a: region::CodeExtent,
-                        scope_b: region::CodeExtent)
-                        -> RelateResult<'tcx, Region>
-    {
-        // We want to generate the intersection of two
-        // scopes or two free regions.  So, if one of
-        // these scopes is a subscope of the other, return
-        // it. Otherwise fail.
-        debug!("intersect_scopes(scope_a={:?}, scope_b={:?}, region_a={:?}, region_b={:?})",
-               scope_a, scope_b, region_a, region_b);
-        let r_id = self.tcx.region_maps.nearest_common_ancestor(scope_a, scope_b);
-        if r_id == scope_a {
-            Ok(ReScope(scope_b))
-        } else if r_id == scope_b {
-            Ok(ReScope(scope_a))
-        } else {
-            Err(TypeError::RegionsNoOverlap(region_a, region_b))
-        }
-    }
 }
 
 // ______________________________________________________________________
 
-#[derive(Copy, Clone, PartialEq, Debug)]
-enum Classification { Expanding, Contracting }
-
 #[derive(Copy, Clone, Debug)]
-pub enum VarValue { NoValue, Value(Region), ErrorValue }
+pub enum VarValue { Value(Region), ErrorValue }
 
 struct VarData {
-    classification: Classification,
     value: VarValue,
 }
 
@@ -1005,12 +862,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
     fn construct_var_data(&self) -> Vec<VarData> {
         (0..self.num_vars() as usize).map(|_| {
             VarData {
-                // All nodes are initially classified as contracting; during
-                // the expansion phase, we will shift the classification for
-                // those nodes that have a concrete region predecessor to
-                // Expanding.
-                classification: Contracting,
-                value: NoValue,
+                value: Value(ty::ReEmpty),
             }
         }).collect()
     }
@@ -1062,11 +914,11 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
               }
               ConstrainVarSubVar(a_vid, b_vid) => {
                 match var_data[a_vid.index as usize].value {
-                  NoValue | ErrorValue => false,
-                  Value(a_region) => {
-                    let b_node = &mut var_data[b_vid.index as usize];
-                    self.expand_node(free_regions, a_region, b_vid, b_node)
-                  }
+                    ErrorValue => false,
+                    Value(a_region) => {
+                        let b_node = &mut var_data[b_vid.index as usize];
+                        self.expand_node(free_regions, a_region, b_vid, b_node)
+                    }
                 }
               }
               ConstrainVarSubReg(..) => {
@@ -1100,16 +952,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
             _ => { }
         }
 
-        b_data.classification = Expanding;
         match b_data.value {
-          NoValue => {
-            debug!("Setting initial value of {:?} to {:?}",
-                   b_vid, a_region);
-
-            b_data.value = Value(a_region);
-            return true;
-          }
-
           Value(cur_region) => {
             let lub = self.lub_concrete_regions(free_regions, a_region, cur_region);
             if lub == cur_region {
@@ -1131,6 +974,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         }
     }
 
+    // FIXME(#29436) -- this fn would just go away if we removed ConstrainVarSubReg
     fn contraction(&self,
                    free_regions: &FreeRegionMap,
                    var_data: &mut [VarData]) {
@@ -1142,104 +986,31 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                                    .unwrap()
                                    );
             match *constraint {
-              ConstrainRegSubVar(..) => {
-                // This is an expansion constraint.  Ignore.
-                false
-              }
-              ConstrainVarSubVar(a_vid, b_vid) => {
-                match var_data[b_vid.index as usize].value {
-                  NoValue | ErrorValue => false,
-                  Value(b_region) => {
-                    let a_data = &mut var_data[a_vid.index as usize];
-                    self.contract_node(free_regions, a_vid, a_data, b_region)
-                  }
+                ConstrainRegSubVar(..) |
+                ConstrainVarSubVar(..) => {
+                    // Expansion will ensure that these constraints hold. Ignore.
                 }
-              }
-              ConstrainVarSubReg(a_vid, b_region) => {
-                let a_data = &mut var_data[a_vid.index as usize];
-                self.contract_node(free_regions, a_vid, a_data, b_region)
-              }
-            }
-        })
-    }
-
-    fn contract_node(&self,
-                     free_regions: &FreeRegionMap,
-                     a_vid: RegionVid,
-                     a_data: &mut VarData,
-                     b_region: Region)
-                     -> bool {
-        debug!("contract_node({:?} == {:?}/{:?}, {:?})",
-               a_vid, a_data.value,
-               a_data.classification, b_region);
-
-        return match a_data.value {
-            NoValue => {
-                assert_eq!(a_data.classification, Contracting);
-                a_data.value = Value(b_region);
-                true // changed
-            }
-
-            ErrorValue => false, // no change
-
-            Value(a_region) => {
-                match a_data.classification {
-                    Expanding =>
-                        check_node(self, free_regions, a_vid, a_data, a_region, b_region),
-                    Contracting =>
-                        adjust_node(self, free_regions, a_vid, a_data, a_region, b_region),
+                ConstrainVarSubReg(a_vid, b_region) => {
+                    let a_data = &mut var_data[a_vid.index as usize];
+                    debug!("contraction: {:?} == {:?}, {:?}", a_vid, a_data.value, b_region);
+
+                    let a_region = match a_data.value {
+                        ErrorValue => return false,
+                        Value(a_region) => a_region,
+                    };
+
+                    if !free_regions.is_subregion_of(self.tcx, a_region, b_region) {
+                        debug!("Setting {:?} to ErrorValue: {:?} not subregion of {:?}",
+                            a_vid,
+                            a_region,
+                            b_region);
+                        a_data.value = ErrorValue;
+                    }
                 }
             }
-        };
 
-        fn check_node(this: &RegionVarBindings,
-                      free_regions: &FreeRegionMap,
-                      a_vid: RegionVid,
-                      a_data: &mut VarData,
-                      a_region: Region,
-                      b_region: Region)
-                      -> bool
-        {
-            if !free_regions.is_subregion_of(this.tcx, a_region, b_region) {
-                debug!("Setting {:?} to ErrorValue: {:?} not subregion of {:?}",
-                       a_vid,
-                       a_region,
-                       b_region);
-                a_data.value = ErrorValue;
-            }
             false
-        }
-
-        fn adjust_node(this: &RegionVarBindings,
-                       free_regions: &FreeRegionMap,
-                       a_vid: RegionVid,
-                       a_data: &mut VarData,
-                       a_region: Region,
-                       b_region: Region)
-                       -> bool {
-            match this.glb_concrete_regions(free_regions, a_region, b_region) {
-                Ok(glb) => {
-                    if glb == a_region {
-                        false
-                    } else {
-                        debug!("Contracting value of {:?} from {:?} to {:?}",
-                               a_vid,
-                               a_region,
-                               glb);
-                        a_data.value = Value(glb);
-                        true
-                    }
-                }
-                Err(_) => {
-                    debug!("Setting {:?} to ErrorValue: no glb of {:?}, {:?}",
-                           a_vid,
-                           a_region,
-                           b_region);
-                    a_data.value = ErrorValue;
-                    false
-                }
-            }
-        }
+        })
     }
 
     fn collect_concrete_region_errors(&self,
@@ -1308,12 +1079,6 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                 Value(_) => {
                     /* Inference successful */
                 }
-                NoValue => {
-                    /* Unconstrained inference: do not report an error
-                       until the value of this variable is requested.
-                       After all, sometimes we make region variables but never
-                       really use their values. */
-                }
                 ErrorValue => {
                     /* Inference impossible, this value contains
                        inconsistent constraints.
@@ -1339,18 +1104,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                        this portion of the code and think hard about it. =) */
 
                     let node_vid = RegionVid { index: idx as u32 };
-                    match var_data[idx].classification {
-                        Expanding => {
-                            self.collect_error_for_expanding_node(
-                                free_regions, graph, var_data, &mut dup_vec,
-                                node_vid, errors);
-                        }
-                        Contracting => {
-                            self.collect_error_for_contracting_node(
-                                free_regions, graph, var_data, &mut dup_vec,
-                                node_vid, errors);
-                        }
-                    }
+                    self.collect_error_for_expanding_node(
+                        free_regions, graph, &mut dup_vec, node_vid, errors);
                 }
             }
         }
@@ -1396,7 +1151,6 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
     fn collect_error_for_expanding_node(&self,
                                         free_regions: &FreeRegionMap,
                                         graph: &RegionGraph,
-                                        var_data: &[VarData],
                                         dup_vec: &mut [u32],
                                         node_idx: RegionVid,
                                         errors: &mut Vec<RegionResolutionError<'tcx>>)
@@ -1404,11 +1158,9 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         // Errors in expanding nodes result from a lower-bound that is
         // not contained by an upper-bound.
         let (mut lower_bounds, lower_dup) =
-            self.collect_concrete_regions(graph, var_data, node_idx,
-                                          graph::INCOMING, dup_vec);
+            self.collect_concrete_regions(graph, node_idx, graph::INCOMING, dup_vec);
         let (mut upper_bounds, upper_dup) =
-            self.collect_concrete_regions(graph, var_data, node_idx,
-                                          graph::OUTGOING, dup_vec);
+            self.collect_concrete_regions(graph, node_idx, graph::OUTGOING, dup_vec);
 
         if lower_dup || upper_dup {
             return;
@@ -1459,59 +1211,8 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                     upper_bounds));
     }
 
-    fn collect_error_for_contracting_node(
-        &self,
-        free_regions: &FreeRegionMap,
-        graph: &RegionGraph,
-        var_data: &[VarData],
-        dup_vec: &mut [u32],
-        node_idx: RegionVid,
-        errors: &mut Vec<RegionResolutionError<'tcx>>)
-    {
-        // Errors in contracting nodes result from two upper-bounds
-        // that have no intersection.
-        let (upper_bounds, dup_found) =
-            self.collect_concrete_regions(graph, var_data, node_idx,
-                                          graph::OUTGOING, dup_vec);
-
-        if dup_found {
-            return;
-        }
-
-        for upper_bound_1 in &upper_bounds {
-            for upper_bound_2 in &upper_bounds {
-                match self.glb_concrete_regions(free_regions,
-                                                upper_bound_1.region,
-                                                upper_bound_2.region) {
-                    Ok(_) => {}
-                    Err(_) => {
-                        let origin = (*self.var_origins.borrow())[node_idx.index as usize].clone();
-                        debug!("region inference error at {:?} for {:?}: \
-                                SupSupConflict sub: {:?} sup: {:?}",
-                               origin, node_idx, upper_bound_1.region, upper_bound_2.region);
-                        errors.push(SupSupConflict(
-                            origin,
-                            upper_bound_1.origin.clone(),
-                            upper_bound_1.region,
-                            upper_bound_2.origin.clone(),
-                            upper_bound_2.region));
-                        return;
-                    }
-                }
-            }
-        }
-
-        self.tcx.sess.span_bug(
-            (*self.var_origins.borrow())[node_idx.index as usize].span(),
-            &format!("collect_error_for_contracting_node() could not find error \
-                     for var {:?}, upper_bounds={:?}",
-                    node_idx,
-                    upper_bounds));
-    }
-
     fn collect_concrete_regions(&self,
                                 graph: &RegionGraph,
-                                var_data: &[VarData],
                                 orig_node_idx: RegionVid,
                                 dir: Direction,
                                 dup_vec: &mut [u32])
@@ -1536,7 +1237,6 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
 
         while !state.stack.is_empty() {
             let node_idx = state.stack.pop().unwrap();
-            let classification = var_data[node_idx.index as usize].classification;
 
             // check whether we've visited this node on some previous walk
             if dup_vec[node_idx.index as usize] == u32::MAX {
@@ -1545,17 +1245,12 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                 state.dup_found = true;
             }
 
-            debug!("collect_concrete_regions(orig_node_idx={:?}, node_idx={:?}, \
-                    classification={:?})",
-                   orig_node_idx, node_idx, classification);
+            debug!("collect_concrete_regions(orig_node_idx={:?}, node_idx={:?})",
+                   orig_node_idx, node_idx);
 
             // figure out the direction from which this node takes its
             // values, and search for concrete regions etc in that direction
-            let dir = match classification {
-                Expanding => graph::INCOMING,
-                Contracting => graph::OUTGOING,
-            };
-
+            let dir = graph::INCOMING;
             process_edges(self, &mut state, graph, node_idx, dir);
         }
 
@@ -1638,7 +1333,6 @@ fn normalize(values: &Vec<VarValue>, r: ty::Region) -> ty::Region {
 fn lookup(values: &Vec<VarValue>, rid: ty::RegionVid) -> ty::Region {
     match values[rid.index as usize] {
         Value(r) => r,
-        NoValue => ReEmpty, // No constraints, return ty::ReEmpty
         ErrorValue => ReStatic, // Previously reported error.
     }
 }
index 155f5f44002f428826a966b59b687a5db3107d90..2cd686fde156ed755996aa90eb5c803329e7e695 100644 (file)
@@ -18,7 +18,7 @@ use middle::ty::TyVar;
 use middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation};
 use std::mem;
 
-/// "Greatest lower bound" (common subtype)
+/// Ensures `a` is made a subtype of `b`. Returns `a` on success.
 pub struct Sub<'a, 'tcx: 'a> {
     fields: CombineFields<'a, 'tcx>,
 }
@@ -90,7 +90,8 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> {
             }
 
             _ => {
-                combine::super_combine_tys(self.fields.infcx, self, a, b)
+                try!(combine::super_combine_tys(self.fields.infcx, self, a, b));
+                Ok(a)
             }
         }
     }
index 6bb46ac787073d6cc19858efabfd87c081b83846..41aa191ac24d210f23a3e36dd7cf84293ad6fe5c 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use syntax::ast;
 use middle::ty::{self, IntVarValue, Ty};
 use rustc_data_structures::unify::UnifyKey;
-use rustc_front::hir as ast;
 
 pub trait ToType<'tcx> {
     fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx>;
index c042aea829b98ce92618eec9a29dfb4bf7fb71d8..b3e287f6d7d5d7cf13e39ac7194dbe006093d130 100644 (file)
@@ -55,7 +55,7 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
             ty::TyBareFn(_, ref bfty) => bfty.abi == RustIntrinsic,
             _ => return false
         };
-        intrinsic && self.tcx.item_name(def_id) == "transmute"
+        intrinsic && self.tcx.item_name(def_id).as_str() == "transmute"
     }
 
     fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>, id: ast::NodeId) {
index a34571e4acac77097210f33670bdd6fc427b4a8d..03c75fc6cc370e1b45bb94115022f7f837db97ad 100644 (file)
@@ -21,6 +21,7 @@
 
 pub use self::LangItem::*;
 
+use front::map as hir_map;
 use session::Session;
 use metadata::csearch::each_lang_item;
 use middle::def_id::DefId;
@@ -28,7 +29,8 @@ use middle::ty;
 use middle::weak_lang_items;
 use util::nodemap::FnvHashMap;
 
-use rustc_front::attr::AttrMetaMethods;
+use syntax::ast;
+use syntax::attr::AttrMetaMethods;
 use syntax::codemap::{DUMMY_SP, Span};
 use syntax::parse::token::InternedString;
 use rustc_front::visit::Visitor;
@@ -143,21 +145,23 @@ impl LanguageItems {
     )*
 }
 
-struct LanguageItemCollector<'a> {
+struct LanguageItemCollector<'a, 'tcx: 'a> {
     items: LanguageItems,
 
+    ast_map: &'a hir_map::Map<'tcx>,
+
     session: &'a Session,
 
     item_refs: FnvHashMap<&'static str, usize>,
 }
 
-impl<'a, 'v> Visitor<'v> for LanguageItemCollector<'a> {
+impl<'a, 'v, 'tcx> Visitor<'v> for LanguageItemCollector<'a, 'tcx> {
     fn visit_item(&mut self, item: &hir::Item) {
         if let Some(value) = extract(&item.attrs) {
             let item_index = self.item_refs.get(&value[..]).cloned();
 
             if let Some(item_index) = item_index {
-                self.collect_item(item_index, DefId::local(item.id), item.span)
+                self.collect_item(item_index, self.ast_map.local_def_id(item.id), item.span)
             }
         }
 
@@ -165,16 +169,18 @@ impl<'a, 'v> Visitor<'v> for LanguageItemCollector<'a> {
     }
 }
 
-impl<'a> LanguageItemCollector<'a> {
-    pub fn new(session: &'a Session) -> LanguageItemCollector<'a> {
+impl<'a, 'tcx> LanguageItemCollector<'a, 'tcx> {
+    pub fn new(session: &'a Session, ast_map: &'a hir_map::Map<'tcx>)
+               -> LanguageItemCollector<'a, 'tcx> {
         let mut item_refs = FnvHashMap();
 
         $( item_refs.insert($name, $variant as usize); )*
 
         LanguageItemCollector {
             session: session,
+            ast_map: ast_map,
             items: LanguageItems::new(),
-            item_refs: item_refs
+            item_refs: item_refs,
         }
     }
 
@@ -202,8 +208,8 @@ impl<'a> LanguageItemCollector<'a> {
     pub fn collect_external_language_items(&mut self) {
         let crate_store = &self.session.cstore;
         crate_store.iter_crate_data(|crate_number, _crate_metadata| {
-            each_lang_item(crate_store, crate_number, |node_id, item_index| {
-                let def_id = DefId { krate: crate_number, node: node_id };
+            each_lang_item(crate_store, crate_number, |index, item_index| {
+                let def_id = DefId { krate: crate_number, index: index };
                 self.collect_item(item_index, def_id, DUMMY_SP);
                 true
             });
@@ -216,7 +222,7 @@ impl<'a> LanguageItemCollector<'a> {
     }
 }
 
-pub fn extract(attrs: &[hir::Attribute]) -> Option<InternedString> {
+pub fn extract(attrs: &[ast::Attribute]) -> Option<InternedString> {
     for attribute in attrs {
         match attribute.value_str() {
             Some(ref value) if attribute.check_name("lang") => {
@@ -229,9 +235,11 @@ pub fn extract(attrs: &[hir::Attribute]) -> Option<InternedString> {
     return None;
 }
 
-pub fn collect_language_items(krate: &hir::Crate,
-                              session: &Session) -> LanguageItems {
-    let mut collector = LanguageItemCollector::new(session);
+pub fn collect_language_items(session: &Session,
+                              map: &hir_map::Map)
+                              -> LanguageItems {
+    let krate: &hir::Crate = map.krate();
+    let mut collector = LanguageItemCollector::new(session, map);
     collector.collect(krate);
     let LanguageItemCollector { mut items, .. } = collector;
     weak_lang_items::check_crate(krate, session, &mut items);
@@ -285,6 +293,16 @@ lets_do_this! {
     BitOrTraitLangItem,              "bitor",                   bitor_trait;
     ShlTraitLangItem,                "shl",                     shl_trait;
     ShrTraitLangItem,                "shr",                     shr_trait;
+    AddAssignTraitLangItem,          "add_assign",              add_assign_trait;
+    SubAssignTraitLangItem,          "sub_assign",              sub_assign_trait;
+    MulAssignTraitLangItem,          "mul_assign",              mul_assign_trait;
+    DivAssignTraitLangItem,          "div_assign",              div_assign_trait;
+    RemAssignTraitLangItem,          "rem_assign",              rem_assign_trait;
+    BitXorAssignTraitLangItem,       "bitxor_assign",           bitxor_assign_trait;
+    BitAndAssignTraitLangItem,       "bitand_assign",           bitand_assign_trait;
+    BitOrAssignTraitLangItem,        "bitor_assign",            bitor_assign_trait;
+    ShlAssignTraitLangItem,          "shl_assign",              shl_assign_trait;
+    ShrAssignTraitLangItem,          "shr_assign",              shr_assign_trait;
     IndexTraitLangItem,              "index",                   index_trait;
     IndexMutTraitLangItem,           "index_mut",               index_mut_trait;
     RangeStructLangItem,             "range",                   range_struct;
@@ -330,7 +348,6 @@ lets_do_this! {
     EhUnwindResumeLangItem,          "eh_unwind_resume",        eh_unwind_resume;
     MSVCTryFilterLangItem,           "msvc_try_filter",         msvc_try_filter;
 
-    ExchangeHeapLangItem,            "exchange_heap",           exchange_heap;
     OwnedBoxLangItem,                "owned_box",               owned_box;
 
     PhantomDataItem,                 "phantom_data",            phantom_data;
index 561760b29f19ea0d5e0d8e8b8519b5e0811e904e..3b56597d353a308b7c0bf695d892ae137ed4724d 100644 (file)
@@ -383,7 +383,7 @@ fn visit_fn(ir: &mut IrMaps,
                                &*arg.pat,
                                |_bm, arg_id, _x, path1| {
             debug!("adding argument {}", arg_id);
-            let name = path1.node.name;
+            let name = path1.node;
             fn_maps.add_variable(Arg(arg_id, name));
         })
     };
@@ -416,7 +416,7 @@ fn visit_fn(ir: &mut IrMaps,
 fn visit_local(ir: &mut IrMaps, local: &hir::Local) {
     pat_util::pat_bindings(&ir.tcx.def_map, &*local.pat, |_, p_id, sp, path1| {
         debug!("adding local variable {}", p_id);
-        let name = path1.node.name;
+        let name = path1.node;
         ir.add_live_node_for_node(p_id, VarDefNode(sp));
         ir.add_variable(Local(LocalInfo {
           id: p_id,
@@ -431,7 +431,7 @@ fn visit_arm(ir: &mut IrMaps, arm: &hir::Arm) {
         pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| {
             debug!("adding local variable {} from match with bm {:?}",
                    p_id, bm);
-            let name = path1.node.name;
+            let name = path1.node;
             ir.add_live_node_for_node(p_id, VarDefNode(sp));
             ir.add_variable(Local(LocalInfo {
                 id: p_id,
@@ -465,7 +465,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
         let mut call_caps = Vec::new();
         ir.tcx.with_freevars(expr.id, |freevars| {
             for fv in freevars {
-                if let DefLocal(rv) = fv.def {
+                if let DefLocal(_, rv) = fv.def {
                     let fv_ln = ir.add_live_node(FreeVarNode(fv.span));
                     call_caps.push(CaptureInfo {ln: fv_ln,
                                                 var_nid: rv});
@@ -495,7 +495,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
       hir::ExprAgain(_) | hir::ExprLit(_) | hir::ExprRet(..) |
       hir::ExprBlock(..) | hir::ExprAssign(..) | hir::ExprAssignOp(..) |
       hir::ExprStruct(..) | hir::ExprRepeat(..) |
-      hir::ExprParen(..) | hir::ExprInlineAsm(..) | hir::ExprBox(..) |
+      hir::ExprInlineAsm(..) | hir::ExprBox(..) |
       hir::ExprRange(..) => {
           visit::walk_expr(ir, expr);
       }
@@ -688,7 +688,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     }
 
     fn find_loop_scope(&self,
-                       opt_label: Option<ast::Ident>,
+                       opt_label: Option<ast::Name>,
                        id: NodeId,
                        sp: Span)
                        -> NodeId {
@@ -1049,7 +1049,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
           hir::ExprBreak(opt_label) => {
               // Find which label this break jumps to
-              let sc = self.find_loop_scope(opt_label.map(|l| l.node), expr.id, expr.span);
+              let sc = self.find_loop_scope(opt_label.map(|l| l.node.name), expr.id, expr.span);
 
               // Now that we know the label we're going to,
               // look it up in the break loop nodes table
@@ -1063,7 +1063,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
           hir::ExprAgain(opt_label) => {
               // Find which label this expr continues to
-              let sc = self.find_loop_scope(opt_label.map(|l| l.node), expr.id, expr.span);
+              let sc = self.find_loop_scope(opt_label.map(|l| l.node.name), expr.id, expr.span);
 
               // Now that we know the label we're going to,
               // look it up in the continue loop nodes table
@@ -1147,8 +1147,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
           }
 
           hir::ExprIndex(ref l, ref r) |
-          hir::ExprBinary(_, ref l, ref r) |
-          hir::ExprBox(Some(ref l), ref r) => {
+          hir::ExprBinary(_, ref l, ref r) => {
             let r_succ = self.propagate_through_expr(&**r, succ);
             self.propagate_through_expr(&**l, r_succ)
           }
@@ -1158,11 +1157,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             e1.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ))
           }
 
-          hir::ExprBox(None, ref e) |
+          hir::ExprBox(ref e) |
           hir::ExprAddrOf(_, ref e) |
           hir::ExprCast(ref e, _) |
-          hir::ExprUnary(_, ref e) |
-          hir::ExprParen(ref e) => {
+          hir::ExprUnary(_, ref e) => {
             self.propagate_through_expr(&**e, succ)
           }
 
@@ -1270,7 +1268,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
                    -> LiveNode {
         match self.ir.tcx.def_map.borrow().get(&expr.id).unwrap().full_def() {
-          DefLocal(nid) => {
+          DefLocal(_, nid) => {
             let ln = self.live_node(expr.id, expr.span);
             if acc != 0 {
                 self.init_from_succ(ln, succ);
@@ -1400,9 +1398,8 @@ fn check_arm(this: &mut Liveness, arm: &hir::Arm) {
 
 fn check_expr(this: &mut Liveness, expr: &Expr) {
     match expr.node {
-      hir::ExprAssign(ref l, ref r) => {
+      hir::ExprAssign(ref l, _) => {
         this.check_lvalue(&**l);
-        this.visit_expr(&**r);
 
         visit::walk_expr(this, expr);
       }
@@ -1435,7 +1432,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
       hir::ExprCast(..) | hir::ExprUnary(..) | hir::ExprRet(..) |
       hir::ExprBreak(..) | hir::ExprAgain(..) | hir::ExprLit(_) |
       hir::ExprBlock(..) | hir::ExprAddrOf(..) |
-      hir::ExprStruct(..) | hir::ExprRepeat(..) | hir::ExprParen(..) |
+      hir::ExprStruct(..) | hir::ExprRepeat(..) |
       hir::ExprClosure(..) | hir::ExprPath(..) | hir::ExprBox(..) |
       hir::ExprRange(..) => {
         visit::walk_expr(this, expr);
@@ -1520,9 +1517,9 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn check_lvalue(&mut self, expr: &Expr) {
         match expr.node {
             hir::ExprPath(..) => {
-                if let DefLocal(nid) = self.ir.tcx.def_map.borrow().get(&expr.id)
-                                                                   .unwrap()
-                                                                   .full_def() {
+                if let DefLocal(_, nid) = self.ir.tcx.def_map.borrow().get(&expr.id)
+                                                                      .unwrap()
+                                                                      .full_def() {
                     // Assignment to an immutable variable or argument: only legal
                     // if there is no later assignment. If this local is actually
                     // mutable, then check for a reassignment to flag the mutability
@@ -1556,8 +1553,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                                    |_bm, p_id, sp, path1| {
                 let var = self.variable(p_id, sp);
                 // Ignore unused self.
-                let ident = path1.node;
-                if ident.name != special_idents::self_.name {
+                let name = path1.node;
+                if name != special_idents::self_.name {
                     self.warn_about_unused(sp, p_id, entry_ln, var);
                 }
             })
index dd2f48d25b4b0c6cc00c69dbd56b508fa824e141..1fcd6e92305f5f154ce70ff4372c0341413fec0f 100644 (file)
@@ -305,7 +305,7 @@ impl MutabilityCategory {
 
     fn from_local(tcx: &ty::ctxt, id: ast::NodeId) -> MutabilityCategory {
         let ret = match tcx.map.get(id) {
-            ast_map::NodeLocal(p) | ast_map::NodeArg(p) => match p.node {
+            ast_map::NodeLocal(p) => match p.node {
                 hir::PatIdent(bind_mode, _, _) => {
                     if bind_mode == hir::BindByValue(hir::MutMutable) {
                         McDeclared
@@ -474,7 +474,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
                    expr.id,
                    expr,
                    base_cmt);
-            Ok(self.cat_field(expr, base_cmt, f_name.node.name, expr_ty))
+            Ok(self.cat_field(expr, base_cmt, f_name.node, expr_ty))
           }
 
           hir::ExprTupField(ref base, idx) => {
@@ -519,10 +519,6 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
             self.cat_def(expr.id, expr.span, expr_ty, def)
           }
 
-          hir::ExprParen(ref e) => {
-            self.cat_expr(&**e)
-          }
-
           hir::ExprAddrOf(..) | hir::ExprCall(..) |
           hir::ExprAssign(..) | hir::ExprAssignOp(..) |
           hir::ExprClosure(..) | hir::ExprRet(..) |
@@ -555,7 +551,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
           }
           def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
           def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
-          def::DefTyParam(..) | def::DefRegion(_) |
+          def::DefTyParam(..) |
           def::DefLabel(_) | def::DefSelfTy(..) |
           def::DefAssociatedTy(..) => {
               Ok(Rc::new(cmt_ {
@@ -579,7 +575,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
               }))
           }
 
-          def::DefUpvar(var_id, _, fn_node_id) => {
+          def::DefUpvar(_, var_id, _, fn_node_id) => {
               let ty = try!(self.node_ty(fn_node_id));
               match ty.sty {
                   ty::TyClosure(closure_id, _) => {
@@ -604,7 +600,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
               }
           }
 
-          def::DefLocal(vid) => {
+          def::DefLocal(_, vid) => {
             Ok(Rc::new(cmt_ {
                 id: id,
                 span: span,
@@ -1276,7 +1272,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
             // {f1: p1, ..., fN: pN}
             for fp in field_pats {
                 let field_ty = try!(self.pat_ty(&*fp.node.pat)); // see (*2)
-                let cmt_field = self.cat_field(pat, cmt.clone(), fp.node.ident.name, field_ty);
+                let cmt_field = self.cat_field(pat, cmt.clone(), fp.node.name, field_ty);
                 try!(self.cat_pattern_(cmt_field, &*fp.node.pat, op));
             }
           }
@@ -1467,11 +1463,10 @@ impl<'tcx> cmt_<'tcx> {
                 "non-lvalue".to_string()
             }
             cat_local(vid) => {
-                match tcx.map.find(vid) {
-                    Some(ast_map::NodeArg(_)) => {
-                        "argument".to_string()
-                    }
-                    _ => "local variable".to_string()
+                if tcx.map.is_argument(vid) {
+                    "argument".to_string()
+                } else {
+                    "local variable".to_string()
                 }
             }
             cat_deref(_, _, pk) => {
index 3c483f70a4efb53d8cabcbd156f1f04a06672ed5..04a754b82ce5f0b9651cf829114b0de5dd4a6067 100644 (file)
@@ -14,18 +14,19 @@ use middle::ty;
 use util::nodemap::FnvHashMap;
 
 use syntax::ast;
+use syntax::ext::mtwt;
 use rustc_front::hir;
 use rustc_front::util::walk_pat;
-use syntax::codemap::{Span, DUMMY_SP};
+use syntax::codemap::{respan, Span, Spanned, DUMMY_SP};
 
-pub type PatIdMap = FnvHashMap<ast::Ident, ast::NodeId>;
+pub type PatIdMap = FnvHashMap<ast::Name, ast::NodeId>;
 
 // This is used because same-named variables in alternative patterns need to
 // use the NodeId of their namesake in the first pattern.
 pub fn pat_id_map(dm: &DefMap, pat: &hir::Pat) -> PatIdMap {
     let mut map = FnvHashMap();
-    pat_bindings(dm, pat, |_bm, p_id, _s, path1| {
-        map.insert(path1.node, p_id);
+    pat_bindings_hygienic(dm, pat, |_bm, p_id, _s, path1| {
+        map.insert(mtwt::resolve(path1.node), p_id);
     });
     map
 }
@@ -109,12 +110,26 @@ pub fn pat_is_binding_or_wild(dm: &DefMap, pat: &hir::Pat) -> bool {
 /// Call `it` on every "binding" in a pattern, e.g., on `a` in
 /// `match foo() { Some(a) => (), None => () }`
 pub fn pat_bindings<I>(dm: &DefMap, pat: &hir::Pat, mut it: I) where
-    I: FnMut(hir::BindingMode, ast::NodeId, Span, &hir::SpannedIdent),
+    I: FnMut(hir::BindingMode, ast::NodeId, Span, &Spanned<ast::Name>),
 {
     walk_pat(pat, |p| {
         match p.node {
           hir::PatIdent(binding_mode, ref pth, _) if pat_is_binding(dm, p) => {
-            it(binding_mode, p.id, p.span, pth);
+            it(binding_mode, p.id, p.span, &respan(pth.span, pth.node.name));
+          }
+          _ => {}
+        }
+        true
+    });
+}
+
+pub fn pat_bindings_hygienic<I>(dm: &DefMap, pat: &hir::Pat, mut it: I) where
+    I: FnMut(hir::BindingMode, ast::NodeId, Span, &Spanned<ast::Ident>),
+{
+    walk_pat(pat, |p| {
+        match p.node {
+          hir::PatIdent(binding_mode, ref pth, _) if pat_is_binding(dm, p) => {
+            it(binding_mode, p.id, p.span, &respan(pth.span, pth.node));
           }
           _ => {}
         }
@@ -182,10 +197,10 @@ pub fn pat_contains_bindings_or_wild(dm: &DefMap, pat: &hir::Pat) -> bool {
     contains_bindings
 }
 
-pub fn simple_identifier<'a>(pat: &'a hir::Pat) -> Option<&'a ast::Ident> {
+pub fn simple_name<'a>(pat: &'a hir::Pat) -> Option<ast::Name> {
     match pat.node {
         hir::PatIdent(hir::BindByValue(_), ref path1, None) => {
-            Some(&path1.node)
+            Some(path1.node.name)
         }
         _ => {
             None
@@ -197,7 +212,7 @@ pub fn def_to_path(tcx: &ty::ctxt, id: DefId) -> hir::Path {
     tcx.with_path(id, |path| hir::Path {
         global: false,
         segments: path.last().map(|elem| hir::PathSegment {
-            identifier: ast::Ident::new(elem.name()),
+            identifier: ast::Ident::with_empty_ctxt(elem.name()),
             parameters: hir::PathParameters::none(),
         }).into_iter().collect(),
         span: DUMMY_SP,
@@ -205,7 +220,7 @@ pub fn def_to_path(tcx: &ty::ctxt, id: DefId) -> hir::Path {
 }
 
 /// Return variants that are necessary to exist for the pattern to match.
-pub fn necessary_variants(dm: &DefMap, pat: &hir::Pat) -> Vec<ast::NodeId> {
+pub fn necessary_variants(dm: &DefMap, pat: &hir::Pat) -> Vec<DefId> {
     let mut variants = vec![];
     walk_pat(pat, |p| {
         match p.node {
@@ -214,7 +229,7 @@ pub fn necessary_variants(dm: &DefMap, pat: &hir::Pat) -> Vec<ast::NodeId> {
             hir::PatStruct(..) => {
                 match dm.borrow().get(&p.id) {
                     Some(&PathResolution { base_def: DefVariant(_, id, _), .. }) => {
-                        variants.push(id.node);
+                        variants.push(id);
                     }
                     _ => ()
                 }
index 03374fa492e1804df1aacc4c43a2583fb4c5b33a..a89da9704d9fd8d7d845e7b51cb39b474c4b0d6c 100644 (file)
@@ -17,7 +17,7 @@
 
 use front::map as ast_map;
 use middle::def;
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::DefId;
 use middle::ty;
 use middle::privacy;
 use session::config;
@@ -26,8 +26,8 @@ use util::nodemap::NodeSet;
 use std::collections::HashSet;
 use syntax::abi;
 use syntax::ast;
+use syntax::attr;
 use rustc_front::hir;
-use rustc_front::attr;
 use rustc_front::visit::Visitor;
 use rustc_front::visit;
 
@@ -61,20 +61,15 @@ fn method_might_be_inlined(tcx: &ty::ctxt, sig: &hir::MethodSig,
         generics_require_inlining(&sig.generics) {
         return true
     }
-    if impl_src.is_local() {
-        {
-            match tcx.map.find(impl_src.node) {
-                Some(ast_map::NodeItem(item)) => {
-                    item_might_be_inlined(&*item)
-                }
-                Some(..) | None => {
-                    tcx.sess.span_bug(impl_item.span, "impl did is not an item")
-                }
-            }
+    if let Some(impl_node_id) = tcx.map.as_local_node_id(impl_src) {
+        match tcx.map.find(impl_node_id) {
+            Some(ast_map::NodeItem(item)) =>
+                item_might_be_inlined(&*item),
+            Some(..) | None =>
+                tcx.sess.span_bug(impl_item.span, "impl did is not an item")
         }
     } else {
-        tcx.sess.span_bug(impl_item.span, "found a foreign impl as a parent \
-                                           of a local method")
+        tcx.sess.span_bug(impl_item.span, "found a foreign impl as a parent of a local method")
     }
 }
 
@@ -106,22 +101,22 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
                 };
 
                 let def_id = def.def_id();
-                if def_id.is_local() {
+                if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
                     if self.def_id_represents_local_inlined_item(def_id) {
-                        self.worklist.push(def_id.node)
+                        self.worklist.push(node_id);
                     } else {
                         match def {
                             // If this path leads to a constant, then we need to
                             // recurse into the constant to continue finding
                             // items that are reachable.
                             def::DefConst(..) | def::DefAssociatedConst(..) => {
-                                self.worklist.push(def_id.node);
+                                self.worklist.push(node_id);
                             }
 
                             // If this wasn't a static, then the destination is
                             // surely reachable.
                             _ => {
-                                self.reachable_symbols.insert(def_id.node);
+                                self.reachable_symbols.insert(node_id);
                             }
                         }
                     }
@@ -132,11 +127,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
                 let def_id = self.tcx.tables.borrow().method_map[&method_call].def_id;
                 match self.tcx.impl_or_trait_item(def_id).container() {
                     ty::ImplContainer(_) => {
-                        if def_id.is_local() {
+                        if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
                             if self.def_id_represents_local_inlined_item(def_id) {
-                                self.worklist.push(def_id.node)
+                                self.worklist.push(node_id)
                             }
-                            self.reachable_symbols.insert(def_id.node);
+                            self.reachable_symbols.insert(node_id);
                         }
                     }
                     ty::TraitContainer(_) => {}
@@ -171,11 +166,11 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
     // Returns true if the given def ID represents a local item that is
     // eligible for inlining and false otherwise.
     fn def_id_represents_local_inlined_item(&self, def_id: DefId) -> bool {
-        if def_id.krate != LOCAL_CRATE {
-            return false
-        }
+        let node_id = match self.tcx.map.as_local_node_id(def_id) {
+            Some(node_id) => node_id,
+            None => { return false; }
+        };
 
-        let node_id = def_id.node;
         match self.tcx.map.find(node_id) {
             Some(ast_map::NodeItem(item)) => {
                 match item.node {
@@ -204,11 +199,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
                             // Check the impl. If the generics on the self
                             // type of the impl require inlining, this method
                             // does too.
-                            assert!(impl_did.is_local());
-                            match self.tcx
-                                      .map
-                                      .expect_item(impl_did.node)
-                                      .node {
+                            let impl_node_id = self.tcx.map.as_local_node_id(impl_did).unwrap();
+                            match self.tcx.map.expect_item(impl_node_id).node {
                                 hir::ItemImpl(_, _, ref generics, _, _, _) => {
                                     generics_require_inlining(generics)
                                 }
@@ -354,8 +346,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
         drop_trait.for_each_impl(self.tcx, |drop_impl| {
             for destructor in &self.tcx.impl_items.borrow()[&drop_impl] {
                 let destructor_did = destructor.def_id();
-                if destructor_did.is_local() {
-                    self.reachable_symbols.insert(destructor_did.node);
+                if let Some(destructor_node_id) = self.tcx.map.as_local_node_id(destructor_did) {
+                    self.reachable_symbols.insert(destructor_node_id);
                 }
             }
         })
@@ -377,8 +369,10 @@ pub fn find_reachable(tcx: &ty::ctxt,
     }
     for (_, item) in tcx.lang_items.items() {
         match *item {
-            Some(did) if did.is_local() => {
-                reachable_context.worklist.push(did.node);
+            Some(did) => {
+                if let Some(node_id) = tcx.map.as_local_node_id(did) {
+                    reachable_context.worklist.push(node_id);
+                }
             }
             _ => {}
         }
index af6211665f162b85c6b2701e10d09ae444b43fc3..1027bbf67037b473638287632808ca0d164ab6b3 100644 (file)
@@ -394,7 +394,7 @@ impl RegionMaps {
         self.code_extents.borrow()[e.0 as usize]
     }
     pub fn each_encl_scope<E>(&self, mut e:E) where E: FnMut(&CodeExtent, &CodeExtent) {
-        for child_id in (1..self.code_extents.borrow().len()) {
+        for child_id in 1..self.code_extents.borrow().len() {
             let child = CodeExtent(child_id as u32);
             if let Some(parent) = self.opt_encl_scope(child) {
                 e(&child, &parent)
@@ -722,7 +722,7 @@ fn resolve_block(visitor: &mut RegionResolutionVisitor, blk: &hir::Block) {
             }
             visitor.visit_stmt(&**statement)
         }
-        visit::walk_expr_opt(visitor, &blk.expr)
+        walk_list!(visitor, visit_expr, &blk.expr);
     }
 
     visitor.cx = prev_cx;
@@ -1011,11 +1011,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &hir::Local) {
                         visitor, &**subexpr, blk_id);
                 }
             }
-            hir::ExprUnary(hir::UnUniq, ref subexpr) => {
-                record_rvalue_scope_if_borrow_expr(visitor, &**subexpr, blk_id);
-            }
-            hir::ExprCast(ref subexpr, _) |
-            hir::ExprParen(ref subexpr) => {
+            hir::ExprCast(ref subexpr, _) => {
                 record_rvalue_scope_if_borrow_expr(visitor, &**subexpr, blk_id)
             }
             hir::ExprBlock(ref block) => {
@@ -1064,8 +1060,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &hir::Local) {
                 hir::ExprUnary(hir::UnDeref, ref subexpr) |
                 hir::ExprField(ref subexpr, _) |
                 hir::ExprTupField(ref subexpr, _) |
-                hir::ExprIndex(ref subexpr, _) |
-                hir::ExprParen(ref subexpr) => {
+                hir::ExprIndex(ref subexpr, _) => {
                     expr = &**subexpr;
                 }
                 _ => {
index 73b3b32f648714068d050aa096694f85c8a594bd..d9398a1c58cd9a65ca4f9dd8822d03f519889e4f 100644 (file)
@@ -73,7 +73,7 @@ struct LifetimeContext<'a> {
     trait_ref_hack: bool,
 
     // List of labels in the function/method currently under analysis.
-    labels_in_fn: Vec<(ast::Ident, Span)>,
+    labels_in_fn: Vec<(ast::Name, Span)>,
 }
 
 enum ScopeChain<'a> {
@@ -195,7 +195,6 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
     fn visit_ty(&mut self, ty: &hir::Ty) {
         match ty.node {
             hir::TyBareFn(ref c) => {
-                visit::walk_lifetime_decls_helper(self, &c.lifetimes);
                 self.with(LateScope(&c.lifetimes, self.scope), |old_scope, this| {
                     // a bare fn has no bounds, so everything
                     // contained within is scoped within its binder.
@@ -245,7 +244,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
                   |_, this| visit::walk_block(this, b));
     }
 
-    fn visit_lifetime_ref(&mut self, lifetime_ref: &hir::Lifetime) {
+    fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) {
         if lifetime_ref.name == special_idents::static_lifetime.name {
             self.insert_lifetime(lifetime_ref, DefStaticRegion);
             return;
@@ -255,7 +254,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
 
     fn visit_generics(&mut self, generics: &hir::Generics) {
         for ty_param in generics.ty_params.iter() {
-            visit::walk_ty_param_bounds_helper(self, &ty_param.bounds);
+            walk_list!(self, visit_ty_param_bound, &ty_param.bounds);
             match ty_param.default {
                 Some(ref ty) => self.visit_ty(&**ty),
                 None => {}
@@ -273,22 +272,22 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
                                                |old_scope, this| {
                             this.check_lifetime_defs(old_scope, bound_lifetimes);
                             this.visit_ty(&**bounded_ty);
-                            visit::walk_ty_param_bounds_helper(this, bounds);
+                            walk_list!(this, visit_ty_param_bound, bounds);
                         });
                         self.trait_ref_hack = false;
                         result
                     } else {
                         self.visit_ty(&**bounded_ty);
-                        visit::walk_ty_param_bounds_helper(self, bounds);
+                        walk_list!(self, visit_ty_param_bound, bounds);
                     }
                 }
                 &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{ref lifetime,
                                                                                 ref bounds,
                                                                                 .. }) => {
 
-                    self.visit_lifetime_ref(lifetime);
+                    self.visit_lifetime(lifetime);
                     for bound in bounds {
-                        self.visit_lifetime_ref(bound);
+                        self.visit_lifetime(bound);
                     }
                 }
                 &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ id,
@@ -357,10 +356,10 @@ fn signal_shadowing_problem(
     sess: &Session, name: ast::Name, orig: Original, shadower: Shadower) {
     if let (ShadowKind::Lifetime, ShadowKind::Lifetime) = (orig.kind, shadower.kind) {
         // lifetime/lifetime shadowing is an error
-        sess.span_err(shadower.span,
-                      &format!("{} name `{}` shadows a \
-                                {} name that is already in scope",
-                               shadower.kind.desc(), name, orig.kind.desc()));
+        span_err!(sess, shadower.span, E0496,
+                  "{} name `{}` shadows a \
+                   {} name that is already in scope",
+                  shadower.kind.desc(), name, orig.kind.desc());
     } else {
         // shadowing involving a label is only a warning, due to issues with
         // labels and lifetimes not being macro-hygienic.
@@ -381,7 +380,7 @@ fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v hir::Block) {
     struct GatherLabels<'a> {
         sess: &'a Session,
         scope: Scope<'a>,
-        labels_in_fn: &'a mut Vec<(ast::Ident, Span)>,
+        labels_in_fn: &'a mut Vec<(ast::Name, Span)>,
     }
 
     let mut gather = GatherLabels {
@@ -403,9 +402,9 @@ fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v hir::Block) {
             if let Some(label) = expression_label(ex) {
                 for &(prior, prior_span) in &self.labels_in_fn[..] {
                     // FIXME (#24278): non-hygienic comparison
-                    if label.name == prior.name {
+                    if label == prior {
                         signal_shadowing_problem(self.sess,
-                                                 label.name,
+                                                 label,
                                                  original_label(prior_span),
                                                  shadower_label(ex.span));
                     }
@@ -426,17 +425,17 @@ fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v hir::Block) {
         }
     }
 
-    fn expression_label(ex: &hir::Expr) -> Option<ast::Ident> {
+    fn expression_label(ex: &hir::Expr) -> Option<ast::Name> {
         match ex.node {
             hir::ExprWhile(_, _, Some(label)) |
-            hir::ExprLoop(_, Some(label)) => Some(label),
+            hir::ExprLoop(_, Some(label)) => Some(label.name),
             _ => None,
         }
     }
 
     fn check_if_label_shadows_lifetime<'a>(sess: &'a Session,
                                            mut scope: Scope<'a>,
-                                           label: ast::Ident,
+                                           label: ast::Name,
                                            label_span: Span) {
         loop {
             match *scope {
@@ -447,10 +446,10 @@ fn extract_labels<'v, 'a>(ctxt: &mut LifetimeContext<'a>, b: &'v hir::Block) {
                 LateScope(lifetimes, s) => {
                     for lifetime_def in lifetimes {
                         // FIXME (#24278): non-hygienic comparison
-                        if label.name == lifetime_def.lifetime.name {
+                        if label == lifetime_def.lifetime.name {
                             signal_shadowing_problem(
                                 sess,
-                                label.name,
+                                label,
                                 original_lifetime(&lifetime_def.lifetime),
                                 shadower_label(label_span));
                             return;
@@ -703,7 +702,7 @@ impl<'a> LifetimeContext<'a> {
     {
         for &(label, label_span) in &self.labels_in_fn {
             // FIXME (#24278): non-hygienic comparison
-            if lifetime.name == label.name {
+            if lifetime.name == label {
                 signal_shadowing_problem(self.sess,
                                          lifetime.name,
                                          original_label(label_span),
@@ -799,7 +798,7 @@ fn early_bound_lifetime_names(generics: &hir::Generics) -> Vec<ast::Name> {
             FreeLifetimeCollector { early_bound: &mut early_bound,
                                     late_bound: &mut late_bound };
         for ty_param in generics.ty_params.iter() {
-            visit::walk_ty_param_bounds_helper(&mut collector, &ty_param.bounds);
+            walk_list!(&mut collector, visit_ty_param_bound, &ty_param.bounds);
         }
         for predicate in &generics.where_clause.predicates {
             match predicate {
@@ -807,15 +806,15 @@ fn early_bound_lifetime_names(generics: &hir::Generics) -> Vec<ast::Name> {
                                                                               ref bounded_ty,
                                                                               ..}) => {
                     collector.visit_ty(&**bounded_ty);
-                    visit::walk_ty_param_bounds_helper(&mut collector, bounds);
+                    walk_list!(&mut collector, visit_ty_param_bound, bounds);
                 }
                 &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{ref lifetime,
                                                                                 ref bounds,
                                                                                 ..}) => {
-                    collector.visit_lifetime_ref(lifetime);
+                    collector.visit_lifetime(lifetime);
 
                     for bound in bounds {
-                        collector.visit_lifetime_ref(bound);
+                        collector.visit_lifetime(bound);
                     }
                 }
                 &hir::WherePredicate::EqPredicate(_) => unimplemented!()
@@ -843,7 +842,7 @@ fn early_bound_lifetime_names(generics: &hir::Generics) -> Vec<ast::Name> {
     }
 
     impl<'a, 'v> Visitor<'v> for FreeLifetimeCollector<'a> {
-        fn visit_lifetime_ref(&mut self, lifetime_ref: &hir::Lifetime) {
+        fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) {
             shuffle(self.early_bound, self.late_bound,
                     lifetime_ref.name);
         }
index 9c4697404201eac242c08128b6f458ce7aff2142..89c0f4f2251e5f30798a0726805c8d4b52aa8894 100644 (file)
 //! A pass that annotates every item and method with its stability level,
 //! propagating default levels lexically from parent to children ast nodes.
 
+pub use self::StabilityLevel::*;
+
 use session::Session;
 use lint;
+use metadata::cstore::LOCAL_CRATE;
 use middle::def;
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::{CRATE_DEF_INDEX, DefId};
 use middle::ty;
 use middle::privacy::PublicItems;
 use metadata::csearch;
 use syntax::parse::token::InternedString;
 use syntax::codemap::{Span, DUMMY_SP};
 use syntax::ast;
-use syntax::ast::NodeId;
+use syntax::ast::{NodeId, Attribute};
 use syntax::feature_gate::{GateIssue, emit_feature_err};
+use syntax::attr::{self, Stability, AttrMetaMethods};
 use util::nodemap::{DefIdMap, FnvHashSet, FnvHashMap};
 
 use rustc_front::hir;
-use rustc_front::hir::{FnDecl, Attribute, Block, Crate, Item, Generics, StructField, Variant};
-use rustc_front::attr::{self, Stability, AttrMetaMethods};
+use rustc_front::hir::{FnDecl, Block, Crate, Item, Generics, StructField, Variant};
 use rustc_front::visit::{self, FnKind, Visitor};
 
 use std::mem::replace;
 use std::cmp::Ordering;
 
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Copy, Debug, Eq, Hash)]
+pub enum StabilityLevel {
+    Unstable,
+    Stable,
+}
+
+impl StabilityLevel {
+    pub fn from_attr_level(level: &attr::StabilityLevel) -> Self {
+        if level.is_stable() { Stable } else { Unstable }
+    }
+}
+
 /// A stability index, giving the stability level for items and methods.
 pub struct Index<'tcx> {
     /// This is mostly a cache, except the stabilities of local items
@@ -66,10 +81,9 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
                     // if parent is deprecated and we're not, inherit this by merging
                     // deprecated_since and its reason.
                     if let Some(parent_stab) = self.parent {
-                        if parent_stab.deprecated_since.is_some()
-                        && stab.deprecated_since.is_none() {
-                            stab.deprecated_since = parent_stab.deprecated_since.clone();
-                            stab.reason = parent_stab.reason.clone();
+                        if parent_stab.depr.is_some()
+                        && stab.depr.is_none() {
+                            stab.depr = parent_stab.depr.clone()
                         }
                     }
 
@@ -77,9 +91,9 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
 
                     // Check if deprecated_since < stable_since. If it is,
                     // this is *almost surely* an accident.
-                    let deprecated_predates_stable = match (stab.deprecated_since.as_ref(),
-                                                            stab.since.as_ref()) {
-                        (Some(dep_since), Some(stab_since)) => {
+                    let deprecated_predates_stable = match (&stab.depr, &stab.level) {
+                        (&Some(attr::Deprecation {since: ref dep_since, ..}),
+                               &attr::Stable {since: ref stab_since}) => {
                             // explicit version of iter::order::lt to handle parse errors properly
                             let mut is_less = false;
                             for (dep_v, stab_v) in dep_since.split(".").zip(stab_since.split(".")) {
@@ -112,10 +126,11 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
                             "An API can't be stabilized after it is deprecated");
                     }
 
-                    self.index.map.insert(DefId::local(id), Some(stab));
+                    let def_id = self.tcx.map.local_def_id(id);
+                    self.index.map.insert(def_id, Some(stab));
 
                     // Don't inherit #[stable(feature = "rust1", since = "1.0.0")]
-                    if stab.level != attr::Stable {
+                    if !stab.level.is_stable() {
                         let parent = replace(&mut self.parent, Some(stab));
                         f(self);
                         self.parent = parent;
@@ -128,7 +143,8 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> {
                            use_parent, self.parent);
                     if use_parent {
                         if let Some(stab) = self.parent {
-                            self.index.map.insert(DefId::local(id), Some(stab));
+                            let def_id = self.tcx.map.local_def_id(id);
+                            self.index.map.insert(def_id, Some(stab));
                         } else if self.index.staged_api[&LOCAL_CRATE] && required
                             && self.export_map.contains(&id)
                             && !self.tcx.sess.opts.test {
@@ -182,9 +198,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Annotator<'a, 'tcx> {
                       |v| visit::walk_item(v, i), required);
 
         if let hir::ItemStruct(ref sd, _) = i.node {
-            sd.ctor_id.map(|id| {
-                self.annotate(id, true, &i.attrs, i.span, |_| {}, true)
-            });
+            if !sd.is_struct() {
+                self.annotate(sd.id(), true, &i.attrs, i.span, |_| {}, true)
+            }
         }
     }
 
@@ -204,9 +220,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Annotator<'a, 'tcx> {
                       |v| visit::walk_impl_item(v, ii), true);
     }
 
-    fn visit_variant(&mut self, var: &Variant, g: &'v Generics) {
-        self.annotate(var.node.id, true, &var.node.attrs, var.span,
-                      |v| visit::walk_variant(v, var, g), true)
+    fn visit_variant(&mut self, var: &Variant, g: &'v Generics, item_id: NodeId) {
+        self.annotate(var.node.data.id(), true, &var.node.attrs, var.span,
+                      |v| visit::walk_variant(v, var, g, item_id), true)
     }
 
     fn visit_struct_field(&mut self, s: &StructField) {
@@ -237,7 +253,7 @@ impl<'tcx> Index<'tcx> {
         for attr in &krate.attrs {
             if &attr.name()[..] == "staged_api" {
                 match attr.node.value.node {
-                    hir::MetaWord(_) => {
+                    ast::MetaWord(_) => {
                         attr::mark_used(attr);
                         is_staged_api = true;
                     }
@@ -258,7 +274,7 @@ impl<'tcx> Index<'tcx> {
 /// features and possibly prints errors. Returns a list of all
 /// features used.
 pub fn check_unstable_api_usage(tcx: &ty::ctxt)
-                                -> FnvHashMap<InternedString, attr::StabilityLevel> {
+                                -> FnvHashMap<InternedString, StabilityLevel> {
     let ref active_lib_features = tcx.sess.features.borrow().declared_lib_features;
 
     // Put the active features into a map for quick lookup
@@ -267,7 +283,8 @@ pub fn check_unstable_api_usage(tcx: &ty::ctxt)
     let mut checker = Checker {
         tcx: tcx,
         active_features: active_features,
-        used_features: FnvHashMap()
+        used_features: FnvHashMap(),
+        in_skip_block: 0,
     };
 
     let krate = tcx.map.krate();
@@ -280,18 +297,27 @@ pub fn check_unstable_api_usage(tcx: &ty::ctxt)
 struct Checker<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
     active_features: FnvHashSet<InternedString>,
-    used_features: FnvHashMap<InternedString, attr::StabilityLevel>
+    used_features: FnvHashMap<InternedString, StabilityLevel>,
+    // Within a block where feature gate checking can be skipped.
+    in_skip_block: u32,
 }
 
 impl<'a, 'tcx> Checker<'a, 'tcx> {
     fn check(&mut self, id: DefId, span: Span, stab: &Option<&Stability>) {
         // Only the cross-crate scenario matters when checking unstable APIs
         let cross_crate = !id.is_local();
-        if !cross_crate { return }
+        if !cross_crate {
+            return
+        }
+
+        // We don't need to check for stability - presumably compiler generated code.
+        if self.in_skip_block > 0 {
+            return;
+        }
 
         match *stab {
-            Some(&Stability { level: attr::Unstable, ref feature, ref reason, issue, .. }) => {
-                self.used_features.insert(feature.clone(), attr::Unstable);
+            Some(&Stability { level: attr::Unstable {ref reason, issue}, ref feature, .. }) => {
+                self.used_features.insert(feature.clone(), Unstable);
 
                 if !self.active_features.contains(feature) {
                     let msg = match *reason {
@@ -299,13 +325,12 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
                                                &feature, &r),
                         None => format!("use of unstable library feature '{}'", &feature)
                     };
-
                     emit_feature_err(&self.tcx.sess.parse_sess.span_diagnostic,
-                                      &feature, span, GateIssue::Library(issue), &msg);
+                                      &feature, span, GateIssue::Library(Some(issue)), &msg);
                 }
             }
-            Some(&Stability { level, ref feature, .. }) => {
-                self.used_features.insert(feature.clone(), level);
+            Some(&Stability { ref level, ref feature, .. }) => {
+                self.used_features.insert(feature.clone(), StabilityLevel::from_attr_level(level));
 
                 // Stable APIs are always ok to call and deprecated APIs are
                 // handled by a lint.
@@ -336,7 +361,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
         // When compiling with --test we don't enforce stability on the
         // compiler-generated test module, demarcated with `DUMMY_SP` plus the
         // name `__test`
-        if item.span == DUMMY_SP && item.ident.name == "__test" { return }
+        if item.span == DUMMY_SP && item.name.as_str() == "__test" { return }
 
         check_item(self.tcx, item, true,
                    &mut |id, sp, stab| self.check(id, sp, stab));
@@ -355,11 +380,32 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
         visit::walk_path(self, path)
     }
 
+    fn visit_path_list_item(&mut self, prefix: &hir::Path, item: &hir::PathListItem) {
+        check_path_list_item(self.tcx, item,
+                   &mut |id, sp, stab| self.check(id, sp, stab));
+        visit::walk_path_list_item(self, prefix, item)
+    }
+
     fn visit_pat(&mut self, pat: &hir::Pat) {
         check_pat(self.tcx, pat,
                   &mut |id, sp, stab| self.check(id, sp, stab));
         visit::walk_pat(self, pat)
     }
+
+    fn visit_block(&mut self, b: &hir::Block) {
+        let old_skip_count = self.in_skip_block;
+        match b.rules {
+            hir::BlockCheckMode::PushUnstableBlock => {
+                self.in_skip_block += 1;
+            }
+            hir::BlockCheckMode::PopUnstableBlock => {
+                self.in_skip_block = self.in_skip_block.checked_sub(1).unwrap();
+            }
+            _ => {}
+        }
+        visit::walk_block(self, b);
+        self.in_skip_block = old_skip_count;
+    }
 }
 
 /// Helper for discovering nodes to check for stability
@@ -374,7 +420,7 @@ pub fn check_item(tcx: &ty::ctxt, item: &hir::Item, warn_about_defns: bool,
                 Some(cnum) => cnum,
                 None => return,
             };
-            let id = DefId { krate: cnum, node: ast::CRATE_NODE_ID };
+            let id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
             maybe_do_stability_check(tcx, id, item.span, cb);
         }
 
@@ -387,7 +433,7 @@ pub fn check_item(tcx: &ty::ctxt, item: &hir::Item, warn_about_defns: bool,
 
             for impl_item in impl_items {
                 let item = trait_items.iter().find(|item| {
-                    item.name() == impl_item.ident.name
+                    item.name() == impl_item.name
                 }).unwrap();
                 if warn_about_defns {
                     maybe_do_stability_check(tcx, item.def_id(), impl_item.span, cb);
@@ -412,7 +458,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &hir::Expr,
         hir::ExprField(ref base_e, ref field) => {
             span = field.span;
             match tcx.expr_ty_adjusted(base_e).sty {
-                ty::TyStruct(def, _) => def.struct_variant().field_named(field.node.name).did,
+                ty::TyStruct(def, _) => def.struct_variant().field_named(field.node).did,
                 _ => tcx.sess.span_bug(e.span,
                                        "stability::check_expr: named field access on non-struct")
             }
@@ -435,7 +481,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &hir::Expr,
                     // in the construction expression.
                     for field in expr_fields {
                         let did = def.struct_variant()
-                            .field_named(field.ident.node.name)
+                            .field_named(field.name.node)
                             .did;
                         maybe_do_stability_check(tcx, did, field.span, cb);
                     }
@@ -465,12 +511,23 @@ pub fn check_path(tcx: &ty::ctxt, path: &hir::Path, id: ast::NodeId,
                   cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
     match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
         Some(def::DefPrimTy(..)) => {}
+        Some(def::DefSelfTy(..)) => {}
         Some(def) => {
             maybe_do_stability_check(tcx, def.def_id(), path.span, cb);
         }
         None => {}
     }
+}
 
+pub fn check_path_list_item(tcx: &ty::ctxt, item: &hir::PathListItem,
+                  cb: &mut FnMut(DefId, Span, &Option<&Stability>)) {
+    match tcx.def_map.borrow().get(&item.node.id()).map(|d| d.full_def()) {
+        Some(def::DefPrimTy(..)) => {}
+        Some(def) => {
+            maybe_do_stability_check(tcx, def.def_id(), item.span, cb);
+        }
+        None => {}
+    }
 }
 
 pub fn check_pat(tcx: &ty::ctxt, pat: &hir::Pat,
@@ -497,7 +554,7 @@ pub fn check_pat(tcx: &ty::ctxt, pat: &hir::Pat,
         // Foo { a, b, c }
         hir::PatStruct(_, ref pat_fields, _) => {
             for field in pat_fields {
-                let did = v.field_named(field.node.ident.name).did;
+                let did = v.field_named(field.node.name).did;
                 maybe_do_stability_check(tcx, did, field.span, cb);
             }
         }
@@ -591,7 +648,7 @@ fn lookup_uncached<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stabil
 /// libraries, identify activated features that don't exist and error about them.
 pub fn check_unused_or_stable_features(sess: &Session,
                                        lib_features_used: &FnvHashMap<InternedString,
-                                                                      attr::StabilityLevel>) {
+                                                                      StabilityLevel>) {
     let ref declared_lib_features = sess.features.borrow().declared_lib_features;
     let mut remaining_lib_features: FnvHashMap<InternedString, Span>
         = declared_lib_features.clone().into_iter().collect();
@@ -608,7 +665,7 @@ pub fn check_unused_or_stable_features(sess: &Session,
     for (used_lib_feature, level) in lib_features_used {
         match remaining_lib_features.remove(used_lib_feature) {
             Some(span) => {
-                if *level == attr::Stable {
+                if *level == Stable {
                     sess.add_lint(lint::builtin::STABLE_FEATURES,
                                   ast::CRATE_NODE_ID,
                                   span,
index 87939c45d67c54081afd27254c22ac14c77f557e..a3795a32afca25188db2444f3a76dd544176dd1e 100644 (file)
@@ -17,7 +17,8 @@ use super::PredicateObligation;
 use super::project;
 use super::util;
 
-use middle::def_id::{DefId, LOCAL_CRATE};
+use metadata::cstore::LOCAL_CRATE;
+use middle::def_id::DefId;
 use middle::subst::{Subst, Substs, TypeSpace};
 use middle::ty::{self, ToPolyTraitRef, Ty};
 use middle::infer::{self, InferCtxt};
index 4580e642d17dfeb6b4f77163f0fa780d00ca283e..a54818b2b5369b4cac579f84af0d97baff382c85 100644 (file)
@@ -32,7 +32,7 @@ use util::nodemap::{FnvHashMap, FnvHashSet};
 
 use std::fmt;
 use syntax::codemap::Span;
-use rustc_front::attr::{AttributeMethods, AttrMetaMethods};
+use syntax::attr::{AttributeMethods, AttrMetaMethods};
 
 #[derive(Debug, PartialEq, Eq, Hash)]
 pub struct TraitErrorKey<'tcx> {
@@ -216,7 +216,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                     is_warning, infcx.tcx.sess, obligation.cause.span, E0276,
                     "the requirement `{}` appears on the impl \
                      method but not on the corresponding trait method",
-                    obligation.predicate);;
+                    obligation.predicate);
             } else {
                 match obligation.predicate {
                     ty::Predicate::Trait(ref trait_predicate) => {
@@ -276,9 +276,12 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                     }
 
                     ty::Predicate::ObjectSafe(trait_def_id) => {
+                        let violations = object_safety_violations(
+                            infcx.tcx, trait_def_id);
                         report_object_safety_error(infcx.tcx,
                                                    obligation.cause.span,
                                                    trait_def_id,
+                                                   violations,
                                                    is_warning);
                         note_obligation_cause(infcx, obligation);
                     }
@@ -314,7 +317,9 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
         }
 
         TraitNotObjectSafe(did) => {
-            report_object_safety_error(infcx.tcx, obligation.cause.span, did, is_warning);
+            let violations = object_safety_violations(infcx.tcx, did);
+            report_object_safety_error(infcx.tcx, obligation.cause.span, did,
+                                       violations, is_warning);
             note_obligation_cause(infcx, obligation);
         }
     }
@@ -323,6 +328,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
 pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>,
                                         span: Span,
                                         trait_def_id: DefId,
+                                        violations: Vec<ObjectSafetyViolation>,
                                         is_warning: bool)
 {
     span_err_or_warn!(
@@ -331,7 +337,7 @@ pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>,
         tcx.item_path_str(trait_def_id));
 
     let mut reported_violations = FnvHashSet();
-    for violation in object_safety_violations(tcx, trait_def_id) {
+    for violation in violations {
         if !reported_violations.insert(violation.clone()) {
             continue;
         }
@@ -449,7 +455,7 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
             if !infcx.tcx.sess.has_errors() {
                 span_err!(infcx.tcx.sess, obligation.cause.span, E0284,
                         "type annotations required: cannot resolve `{}`",
-                        predicate);;
+                        predicate);
                 note_obligation_cause(infcx, obligation);
             }
         }
index 7f76cfaee58661266d925b1dd77179174fb9bf94..a037621f5c02545265b5fc7ae4a87845083dbe9a 100644 (file)
@@ -39,6 +39,7 @@ pub use self::project::MismatchedProjectionTypes;
 pub use self::project::normalize;
 pub use self::project::Normalized;
 pub use self::object_safety::is_object_safe;
+pub use self::object_safety::astconv_object_safety_violations;
 pub use self::object_safety::object_safety_violations;
 pub use self::object_safety::ObjectSafetyViolation;
 pub use self::object_safety::MethodViolationCode;
index 333d23e6eca8b48ba06802edfa907da43e341210..934c35fa20bc8c1e7eb90f12725e062991dc5c2c 100644 (file)
@@ -23,7 +23,7 @@ use super::elaborate_predicates;
 use middle::def_id::DefId;
 use middle::subst::{self, SelfSpace, TypeSpace};
 use middle::traits;
-use middle::ty::{self, ToPolyTraitRef, Ty};
+use middle::ty::{self, HasTypeFlags, ToPolyTraitRef, Ty};
 use std::rc::Rc;
 use syntax::ast;
 
@@ -76,6 +76,27 @@ pub fn is_object_safe<'tcx>(tcx: &ty::ctxt<'tcx>,
     result
 }
 
+/// Returns the object safety violations that affect
+/// astconv - currently, Self in supertraits. This is needed
+/// because `object_safety_violations` can't be used during
+/// type collection.
+pub fn astconv_object_safety_violations<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                              trait_def_id: DefId)
+                                              -> Vec<ObjectSafetyViolation<'tcx>>
+{
+    let mut violations = vec![];
+
+    if supertraits_reference_self(tcx, trait_def_id) {
+        violations.push(ObjectSafetyViolation::SupertraitSelf);
+    }
+
+    debug!("object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
+           trait_def_id,
+           violations);
+
+    violations
+}
+
 pub fn object_safety_violations<'tcx>(tcx: &ty::ctxt<'tcx>,
                                       trait_def_id: DefId)
                                       -> Vec<ObjectSafetyViolation<'tcx>>
@@ -118,9 +139,9 @@ fn object_safety_violations_for_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
     violations
 }
 
-fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                    trait_def_id: DefId)
-                                    -> bool
+pub fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                        trait_def_id: DefId)
+                                        -> bool
 {
     let trait_def = tcx.lookup_trait_def(trait_def_id);
     let trait_ref = trait_def.trait_ref.clone();
@@ -137,7 +158,7 @@ fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>,
                     data.0.trait_ref.substs.types.get_slice(TypeSpace)
                                                  .iter()
                                                  .cloned()
-                                                 .any(is_self)
+                                                 .any(|t| t.has_self_ty())
                 }
                 ty::Predicate::Projection(..) |
                 ty::Predicate::WellFormed(..) |
@@ -177,7 +198,7 @@ fn generics_require_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
         .any(|predicate| {
             match predicate {
                 ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => {
-                    is_self(trait_pred.0.self_ty())
+                    trait_pred.0.self_ty().is_self()
                 }
                 ty::Predicate::Projection(..) |
                 ty::Predicate::Trait(..) |
@@ -355,10 +376,3 @@ fn contains_illegal_self_type_reference<'tcx>(tcx: &ty::ctxt<'tcx>,
 
     error
 }
-
-fn is_self<'tcx>(ty: Ty<'tcx>) -> bool {
-    match ty.sty {
-        ty::TyParam(ref data) => data.space == subst::SelfSpace,
-        _ => false,
-    }
-}
index 6f422018c13d595fd94b6038cbcb917ebb5d7efa..f6e35cf739d627f0d88487762766f6b172f86705 100644 (file)
@@ -37,7 +37,7 @@ use super::{VtableImplData, VtableObjectData, VtableBuiltinData,
 use super::object_safety;
 use super::util;
 
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::DefId;
 use middle::infer;
 use middle::infer::{InferCtxt, TypeFreshener};
 use middle::subst::{Subst, Substs, TypeSpace};
@@ -1719,7 +1719,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
             ty::TyTuple(ref tys) => ok_if(tys.clone()),
 
-            ty::TyClosure(def_id, ref substs) => {
+            ty::TyClosure(_, ref substs) => {
                 // FIXME -- This case is tricky. In the case of by-ref
                 // closures particularly, we need the results of
                 // inference to decide how to reflect the type of each
@@ -1729,7 +1729,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // captures are by value. Really what we ought to do
                 // is reserve judgement and then intertwine this
                 // analysis with closure inference.
-                assert_eq!(def_id.krate, LOCAL_CRATE);
 
                 // Unboxed closures shouldn't be
                 // implicitly copyable
@@ -1863,7 +1862,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 tys.clone()
             }
 
-            ty::TyClosure(def_id, ref substs) => {
+            ty::TyClosure(_, ref substs) => {
                 // FIXME(#27086). We are invariant w/r/t our
                 // substs.func_substs, but we don't see them as
                 // constituent types; this seems RIGHT but also like
@@ -1872,7 +1871,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // OIBIT interact? That is, there is no way to say
                 // "make me invariant with respect to this TYPE, but
                 // do not act as though I can reach it"
-                assert_eq!(def_id.krate, LOCAL_CRATE);
                 substs.upvar_tys.clone()
             }
 
@@ -2396,7 +2394,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     /// errors as if there is no applicable impl, but rather report
     /// errors are about mismatched argument types.
     ///
-    /// Here is an example. Imagine we have an closure expression
+    /// Here is an example. Imagine we have a closure expression
     /// and we desugared it so that the type of the expression is
     /// `Closure`, and `Closure` expects an int as argument. Then it
     /// is "as if" the compiler generated this impl:
index 1c5156aab02be9c0a53b57df21167d87e51d57d9..c50c9e9765d25ce4a5bdd99d97fc70752b3dc791 100644 (file)
@@ -408,7 +408,7 @@ pub fn upcast<'tcx>(tcx: &ty::ctxt<'tcx>,
         .collect()
 }
 
-/// Given an trait `trait_ref`, returns the number of vtable entries
+/// Given a trait `trait_ref`, returns the number of vtable entries
 /// that come from `trait_ref`, excluding its supertraits. Used in
 /// computing the vtable base for an upcast trait of a trait object.
 pub fn count_own_vtable_entries<'tcx>(tcx: &ty::ctxt<'tcx>,
index cadab499c0765573225589f1b09f713ffc4e5b1e..c44ebcfdb693c36c87f2cdfd94c742af11a4ba53 100644 (file)
@@ -48,7 +48,7 @@ pub enum AutoAdjustment<'tcx> {
 ///
 /// 1. The simplest cases are where the pointer is not adjusted fat vs thin.
 /// Here the pointer will be dereferenced N times (where a dereference can
-/// happen to to raw or borrowed pointers or any smart pointer which implements
+/// happen to raw or borrowed pointers or any smart pointer which implements
 /// Deref, including Box<_>). The number of dereferences is given by
 /// `autoderefs`.  It can then be auto-referenced zero or one times, indicated
 /// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is
index 8cb4f941a2264eb8fc84a2e98c2022f6a6c76f97..8233b6b2b2b6e7a61f4a16e3f5ce45442b6814c2 100644 (file)
@@ -13,7 +13,7 @@
 
 use middle::ty::{self, Ty};
 
-use rustc_front::hir as ast;
+use syntax::ast;
 
 /// Types that are represented as ints.
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
index bcce9e8ea54761d2f73b37728a349a2372698174..afe88f70d945055a4ed325a317c18bc919489345 100644 (file)
@@ -16,7 +16,7 @@ use util::nodemap::FnvHashMap;
 use std::fmt;
 use std::ops;
 
-use rustc_front::hir;
+use syntax::ast;
 
 /// Type contents is how the type checker reasons about kinds.
 /// They track what kinds of things are found within a type.  You can
@@ -182,7 +182,7 @@ impl<'tcx> ty::TyS<'tcx> {
 
             let result = match ty.sty {
                 // usize and isize are ffi-unsafe
-                ty::TyUint(hir::TyUs) | ty::TyInt(hir::TyIs) => {
+                ty::TyUint(ast::TyUs) | ty::TyInt(ast::TyIs) => {
                     TC::None
                 }
 
index ef9707967f39d663319be0eb64f54b78e33f840e..830232cf373b8fe02115ac4f07e4efcf27eb7c24 100644 (file)
@@ -16,6 +16,7 @@
 use front::map as ast_map;
 use session::Session;
 use lint;
+use metadata::csearch;
 use middle;
 use middle::def::DefMap;
 use middle::def_id::DefId;
@@ -41,11 +42,11 @@ use std::cell::{Cell, RefCell, Ref};
 use std::hash::{Hash, Hasher};
 use std::rc::Rc;
 use syntax::abi;
-use syntax::ast::{Name, NodeId};
+use syntax::ast::{self, Name, NodeId};
+use syntax::attr;
 use syntax::parse::token::special_idents;
 
 use rustc_front::hir;
-use rustc_front::attr;
 
 /// Internal storage
 pub struct CtxtArenas<'tcx> {
@@ -134,6 +135,40 @@ impl<'tcx> Tables<'tcx> {
             closure_kinds: DefIdMap(),
         }
     }
+
+    pub fn closure_kind(this: &RefCell<Self>,
+                        tcx: &ty::ctxt<'tcx>,
+                        def_id: DefId)
+                        -> ty::ClosureKind {
+        // If this is a local def-id, it should be inserted into the
+        // tables by typeck; else, it will be retreived from
+        // the external crate metadata.
+        if let Some(&kind) = this.borrow().closure_kinds.get(&def_id) {
+            return kind;
+        }
+
+        let kind = csearch::closure_kind(tcx, def_id);
+        this.borrow_mut().closure_kinds.insert(def_id, kind);
+        kind
+    }
+
+    pub fn closure_type(this: &RefCell<Self>,
+                        tcx: &ty::ctxt<'tcx>,
+                        def_id: DefId,
+                        substs: &ClosureSubsts<'tcx>)
+                        -> ty::ClosureTy<'tcx>
+    {
+        // If this is a local def-id, it should be inserted into the
+        // tables by typeck; else, it will be retreived from
+        // the external crate metadata.
+        if let Some(ty) = this.borrow().closure_tys.get(&def_id) {
+            return ty.subst(tcx, &substs.func_substs);
+        }
+
+        let ty = csearch::closure_ty(tcx, def_id);
+        this.borrow_mut().closure_tys.insert(def_id, ty.clone());
+        ty.subst(tcx, &substs.func_substs)
+    }
 }
 
 impl<'tcx> CommonTypes<'tcx> {
@@ -146,18 +181,18 @@ impl<'tcx> CommonTypes<'tcx> {
             bool: mk(TyBool),
             char: mk(TyChar),
             err: mk(TyError),
-            isize: mk(TyInt(hir::TyIs)),
-            i8: mk(TyInt(hir::TyI8)),
-            i16: mk(TyInt(hir::TyI16)),
-            i32: mk(TyInt(hir::TyI32)),
-            i64: mk(TyInt(hir::TyI64)),
-            usize: mk(TyUint(hir::TyUs)),
-            u8: mk(TyUint(hir::TyU8)),
-            u16: mk(TyUint(hir::TyU16)),
-            u32: mk(TyUint(hir::TyU32)),
-            u64: mk(TyUint(hir::TyU64)),
-            f32: mk(TyFloat(hir::TyF32)),
-            f64: mk(TyFloat(hir::TyF64)),
+            isize: mk(TyInt(ast::TyIs)),
+            i8: mk(TyInt(ast::TyI8)),
+            i16: mk(TyInt(ast::TyI16)),
+            i32: mk(TyInt(ast::TyI32)),
+            i64: mk(TyInt(ast::TyI64)),
+            usize: mk(TyUint(ast::TyUs)),
+            u8: mk(TyUint(ast::TyU8)),
+            u16: mk(TyUint(ast::TyU16)),
+            u32: mk(TyUint(ast::TyU32)),
+            u64: mk(TyUint(ast::TyU64)),
+            f32: mk(TyFloat(ast::TyF32)),
+            f64: mk(TyFloat(ast::TyF64)),
         }
     }
 }
@@ -184,7 +219,7 @@ pub struct ctxt<'tcx> {
     /// Common types, pre-interned for your convenience.
     pub types: CommonTypes<'tcx>,
 
-    pub sess: Session,
+    pub sess: &'tcx Session,
     pub def_map: DefMap,
 
     pub named_region_map: resolve_lifetime::NamedRegionMap,
@@ -235,8 +270,6 @@ pub struct ctxt<'tcx> {
     pub ty_param_defs: RefCell<NodeMap<ty::TypeParameterDef<'tcx>>>,
     pub normalized_cache: RefCell<FnvHashMap<Ty<'tcx>, Ty<'tcx>>>,
     pub lang_items: middle::lang_items::LanguageItems,
-    /// A mapping of fake provided method def_ids to the default implementation
-    pub provided_method_sources: RefCell<DefIdMap<DefId>>,
 
     /// Maps from def-id of a type or region parameter to its
     /// (inferred) variance.
@@ -274,7 +307,6 @@ pub struct ctxt<'tcx> {
 
     /// These caches are used by const_eval when decoding external constants.
     pub extern_const_statics: RefCell<DefIdMap<NodeId>>,
-    pub extern_const_variants: RefCell<DefIdMap<NodeId>>,
     pub extern_const_fns: RefCell<DefIdMap<NodeId>>,
 
     pub node_lint_levels: RefCell<FnvHashMap<(NodeId, lint::LintId),
@@ -338,19 +370,8 @@ pub struct ctxt<'tcx> {
     /// constitute it.
     pub fragment_infos: RefCell<DefIdMap<Vec<ty::FragmentInfo>>>,
 }
-impl<'tcx> ctxt<'tcx> {
-    pub fn closure_kind(&self, def_id: DefId) -> ty::ClosureKind {
-        *self.tables.borrow().closure_kinds.get(&def_id).unwrap()
-    }
-
-    pub fn closure_type(&self,
-                        def_id: DefId,
-                        substs: &ClosureSubsts<'tcx>)
-                        -> ty::ClosureTy<'tcx>
-    {
-        self.tables.borrow().closure_tys.get(&def_id).unwrap().subst(self, &substs.func_substs)
-    }
 
+impl<'tcx> ctxt<'tcx> {
     pub fn type_parameter_def(&self,
                               node_id: NodeId)
                               -> ty::TypeParameterDef<'tcx>
@@ -422,7 +443,7 @@ impl<'tcx> ctxt<'tcx> {
     /// to the context. The closure enforces that the type context and any interned
     /// value (types, substs, etc.) can only be used while `ty::tls` has a valid
     /// reference to the context, to allow formatting values that need it.
-    pub fn create_and_enter<F, R>(s: Session,
+    pub fn create_and_enter<F, R>(s: &'tcx Session,
                                  arenas: &'tcx CtxtArenas<'tcx>,
                                  def_map: DefMap,
                                  named_region_map: resolve_lifetime::NamedRegionMap,
@@ -431,7 +452,7 @@ impl<'tcx> ctxt<'tcx> {
                                  region_maps: RegionMaps,
                                  lang_items: middle::lang_items::LanguageItems,
                                  stability: stability::Index<'tcx>,
-                                 f: F) -> (Session, R)
+                                 f: F) -> R
                                  where F: FnOnce(&ctxt<'tcx>) -> R
     {
         let interner = RefCell::new(FnvHashMap());
@@ -471,7 +492,6 @@ impl<'tcx> ctxt<'tcx> {
             ty_param_defs: RefCell::new(NodeMap()),
             normalized_cache: RefCell::new(FnvHashMap()),
             lang_items: lang_items,
-            provided_method_sources: RefCell::new(DefIdMap()),
             inherent_impls: RefCell::new(DefIdMap()),
             impl_items: RefCell::new(DefIdMap()),
             used_unsafe: RefCell::new(NodeSet()),
@@ -479,7 +499,6 @@ impl<'tcx> ctxt<'tcx> {
             populated_external_types: RefCell::new(DefIdSet()),
             populated_external_primitive_impls: RefCell::new(DefIdSet()),
             extern_const_statics: RefCell::new(DefIdMap()),
-            extern_const_variants: RefCell::new(DefIdMap()),
             extern_const_fns: RefCell::new(DefIdMap()),
             node_lint_levels: RefCell::new(FnvHashMap()),
             transmute_restrictions: RefCell::new(Vec::new()),
@@ -537,7 +556,6 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
 
 pub mod tls {
     use middle::ty;
-    use session::Session;
 
     use std::fmt;
     use syntax::codemap;
@@ -555,17 +573,15 @@ pub mod tls {
         })
     }
 
-    pub fn enter<'tcx, F: FnOnce(&ty::ctxt<'tcx>) -> R, R>(tcx: ty::ctxt<'tcx>, f: F)
-                                                           -> (Session, R) {
-        let result = codemap::SPAN_DEBUG.with(|span_dbg| {
+    pub fn enter<'tcx, F: FnOnce(&ty::ctxt<'tcx>) -> R, R>(tcx: ty::ctxt<'tcx>, f: F) -> R {
+        codemap::SPAN_DEBUG.with(|span_dbg| {
             let original_span_debug = span_dbg.get();
             span_dbg.set(span_debug);
             let tls_ptr = &tcx as *const _ as *const ThreadLocalTyCx;
             let result = TLS_TCX.set(unsafe { &*tls_ptr }, || f(&tcx));
             span_dbg.set(original_span_debug);
             result
-        });
-        (tcx.sess, result)
+        })
     }
 
     pub fn with<F: FnOnce(&ty::ctxt) -> R, R>(f: F) -> R {
@@ -767,30 +783,30 @@ impl<'tcx> ctxt<'tcx> {
         ctxt::intern_ty(&self.arenas.type_, &self.interner, st)
     }
 
-    pub fn mk_mach_int(&self, tm: hir::IntTy) -> Ty<'tcx> {
+    pub fn mk_mach_int(&self, tm: ast::IntTy) -> Ty<'tcx> {
         match tm {
-            hir::TyIs   => self.types.isize,
-            hir::TyI8   => self.types.i8,
-            hir::TyI16  => self.types.i16,
-            hir::TyI32  => self.types.i32,
-            hir::TyI64  => self.types.i64,
+            ast::TyIs   => self.types.isize,
+            ast::TyI8   => self.types.i8,
+            ast::TyI16  => self.types.i16,
+            ast::TyI32  => self.types.i32,
+            ast::TyI64  => self.types.i64,
         }
     }
 
-    pub fn mk_mach_uint(&self, tm: hir::UintTy) -> Ty<'tcx> {
+    pub fn mk_mach_uint(&self, tm: ast::UintTy) -> Ty<'tcx> {
         match tm {
-            hir::TyUs   => self.types.usize,
-            hir::TyU8   => self.types.u8,
-            hir::TyU16  => self.types.u16,
-            hir::TyU32  => self.types.u32,
-            hir::TyU64  => self.types.u64,
+            ast::TyUs   => self.types.usize,
+            ast::TyU8   => self.types.u8,
+            ast::TyU16  => self.types.u16,
+            ast::TyU32  => self.types.u32,
+            ast::TyU64  => self.types.u64,
         }
     }
 
-    pub fn mk_mach_float(&self, tm: hir::FloatTy) -> Ty<'tcx> {
+    pub fn mk_mach_float(&self, tm: ast::FloatTy) -> Ty<'tcx> {
         match tm {
-            hir::TyF32  => self.types.f32,
-            hir::TyF64  => self.types.f64,
+            ast::TyF32  => self.types.f32,
+            ast::TyF64  => self.types.f64,
         }
     }
 
index 72c4366c5bcd5a8f189a1fef6080eed41527de69..61536934aae13cebbae6cd7a8900f7bee6446f76 100644 (file)
@@ -15,7 +15,7 @@ use middle::ty::{self, BoundRegion, Region, Ty};
 
 use std::fmt;
 use syntax::abi;
-use syntax::ast::Name;
+use syntax::ast::{self, Name};
 use syntax::codemap::Span;
 
 use rustc_front::hir;
@@ -49,7 +49,7 @@ pub enum TypeError<'tcx> {
     Sorts(ExpectedFound<Ty<'tcx>>),
     IntegerAsChar,
     IntMismatch(ExpectedFound<ty::IntVarValue>),
-    FloatMismatch(ExpectedFound<hir::FloatTy>),
+    FloatMismatch(ExpectedFound<ast::FloatTy>),
     Traits(ExpectedFound<DefId>),
     BuiltinBoundsMismatch(ExpectedFound<ty::BuiltinBounds>),
     VariadicMismatch(ExpectedFound<bool>),
@@ -302,13 +302,15 @@ impl<'tcx> ty::ctxt<'tcx> {
                                              expected.ty,
                                              found.ty));
 
-                match (expected.def_id.is_local(),
-                       self.map.opt_span(expected.def_id.node)) {
-                    (true, Some(span)) => {
+                match
+                    self.map.as_local_node_id(expected.def_id)
+                            .and_then(|node_id| self.map.opt_span(node_id))
+                {
+                    Some(span) => {
                         self.sess.span_note(span,
                                             &format!("a default was defined here..."));
                     }
-                    (_, _) => {
+                    None => {
                         self.sess.note(
                             &format!("a default is defined on `{}`",
                                      self.item_path_str(expected.def_id)));
@@ -319,13 +321,15 @@ impl<'tcx> ty::ctxt<'tcx> {
                     expected.origin_span,
                     &format!("...that was applied to an unconstrained type variable here"));
 
-                match (found.def_id.is_local(),
-                       self.map.opt_span(found.def_id.node)) {
-                    (true, Some(span)) => {
+                match
+                    self.map.as_local_node_id(found.def_id)
+                            .and_then(|node_id| self.map.opt_span(node_id))
+                {
+                    Some(span) => {
                         self.sess.span_note(span,
                                             &format!("a second default was defined here..."));
                     }
-                    (_, _) => {
+                    None => {
                         self.sess.note(
                             &format!("a second default is defined on `{}`",
                                      self.item_path_str(found.def_id)));
index 2b81be19182e2d525e568e97d678c402481f448b..77608f4012845d687c7054bc0fc4562202d83f8f 100644 (file)
@@ -10,7 +10,7 @@
 
 use middle::def_id::DefId;
 use middle::ty::{self, Ty};
-use rustc_front::hir;
+use syntax::ast;
 
 use self::SimplifiedType::*;
 
@@ -19,9 +19,9 @@ use self::SimplifiedType::*;
 pub enum SimplifiedType {
     BoolSimplifiedType,
     CharSimplifiedType,
-    IntSimplifiedType(hir::IntTy),
-    UintSimplifiedType(hir::UintTy),
-    FloatSimplifiedType(hir::FloatTy),
+    IntSimplifiedType(ast::IntTy),
+    UintSimplifiedType(ast::UintTy),
+    FloatSimplifiedType(ast::FloatTy),
     EnumSimplifiedType(DefId),
     StrSimplifiedType,
     VecSimplifiedType,
index 3025d7b58979fe0fcbdfe96c12cd21f9816e7b52..573634414932bb7ef708f6a40f8cb9d79959240a 100644 (file)
@@ -22,9 +22,10 @@ pub use self::LvaluePreference::*;
 use front::map as ast_map;
 use front::map::LinkedPath;
 use metadata::csearch;
+use metadata::cstore::LOCAL_CRATE;
 use middle;
 use middle::def::{self, ExportMap};
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::DefId;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
 use middle::subst::{self, ParamSpace, Subst, Substs, VecPerParamSpace};
 use middle::traits;
@@ -44,13 +45,13 @@ use std::slice;
 use std::vec::IntoIter;
 use std::collections::{HashMap, HashSet};
 use syntax::ast::{self, CrateNum, Name, NodeId};
+use syntax::attr::{self, AttrMetaMethods};
 use syntax::codemap::Span;
 use syntax::parse::token::{InternedString, special_idents};
 
 use rustc_front::hir;
 use rustc_front::hir::{ItemImpl, ItemTrait};
 use rustc_front::hir::{MutImmutable, MutMutable, Visibility};
-use rustc_front::attr::{self, AttrMetaMethods};
 
 pub use self::sty::{Binder, DebruijnIndex};
 pub use self::sty::{BuiltinBound, BuiltinBounds, ExistentialBounds};
@@ -101,12 +102,12 @@ pub const INITIAL_DISCRIMINANT_VALUE: Disr = 0;
 
 /// The complete set of all analyses described in this module. This is
 /// produced by the driver and fed to trans and later passes.
-pub struct CrateAnalysis {
+pub struct CrateAnalysis<'a> {
     pub export_map: ExportMap,
     pub exported_items: middle::privacy::ExportedItems,
     pub public_items: middle::privacy::PublicItems,
     pub reachable: NodeSet,
-    pub name: String,
+    pub name: &'a str,
     pub glob_map: Option<GlobMap>,
 }
 
@@ -235,9 +236,6 @@ pub struct Method<'tcx> {
     pub vis: hir::Visibility,
     pub def_id: DefId,
     pub container: ImplOrTraitItemContainer,
-
-    // If this method is provided, we need to know where it came from
-    pub provided_source: Option<DefId>
 }
 
 impl<'tcx> Method<'tcx> {
@@ -248,8 +246,7 @@ impl<'tcx> Method<'tcx> {
                explicit_self: ExplicitSelfCategory,
                vis: hir::Visibility,
                def_id: DefId,
-               container: ImplOrTraitItemContainer,
-               provided_source: Option<DefId>)
+               container: ImplOrTraitItemContainer)
                -> Method<'tcx> {
        Method {
             name: name,
@@ -260,7 +257,6 @@ impl<'tcx> Method<'tcx> {
             vis: vis,
             def_id: def_id,
             container: container,
-            provided_source: provided_source
         }
     }
 
@@ -293,7 +289,7 @@ pub struct AssociatedConst<'tcx> {
     pub vis: hir::Visibility,
     pub def_id: DefId,
     pub container: ImplOrTraitItemContainer,
-    pub default: Option<DefId>,
+    pub has_value: bool
 }
 
 #[derive(Clone, Copy, Debug)]
@@ -371,7 +367,6 @@ pub type MethodMap<'tcx> = FnvHashMap<MethodCall, MethodCallee<'tcx>>;
 pub struct CReaderCacheKey {
     pub cnum: CrateNum,
     pub pos: usize,
-    pub len: usize
 }
 
 /// A restriction that certain types must be the same size. The use of
@@ -577,8 +572,8 @@ pub struct ClosureUpvar<'tcx> {
 
 #[derive(Clone, Copy, PartialEq)]
 pub enum IntVarValue {
-    IntType(hir::IntTy),
-    UintType(hir::UintTy),
+    IntType(ast::IntTy),
+    UintType(ast::UintTy),
 }
 
 /// Default region to use for the bound of objects that are
@@ -622,7 +617,7 @@ pub struct RegionParameterDef {
 impl RegionParameterDef {
     pub fn to_early_bound_region(&self) -> ty::Region {
         ty::ReEarlyBound(ty::EarlyBoundRegion {
-            param_id: self.def_id.node,
+            def_id: self.def_id,
             space: self.space,
             index: self.index,
             name: self.name,
@@ -1129,7 +1124,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                         // associated types don't have their own entry (for some reason),
                         // so for now just grab environment for the impl
                         let impl_id = cx.map.get_parent(id);
-                        let impl_def_id = DefId::local(impl_id);
+                        let impl_def_id = cx.map.local_def_id(impl_id);
                         let scheme = cx.lookup_item_type(impl_def_id);
                         let predicates = cx.lookup_predicates(impl_def_id);
                         cx.construct_parameter_environment(impl_item.span,
@@ -1138,7 +1133,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                                            id)
                     }
                     hir::ConstImplItem(_, _) => {
-                        let def_id = DefId::local(id);
+                        let def_id = cx.map.local_def_id(id);
                         let scheme = cx.lookup_item_type(def_id);
                         let predicates = cx.lookup_predicates(def_id);
                         cx.construct_parameter_environment(impl_item.span,
@@ -1147,7 +1142,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                                            id)
                     }
                     hir::MethodImplItem(_, ref body) => {
-                        let method_def_id = DefId::local(id);
+                        let method_def_id = cx.map.local_def_id(id);
                         match cx.impl_or_trait_item(method_def_id) {
                             MethodTraitItem(ref method_ty) => {
                                 let method_generics = &method_ty.generics;
@@ -1173,7 +1168,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                         // associated types don't have their own entry (for some reason),
                         // so for now just grab environment for the trait
                         let trait_id = cx.map.get_parent(id);
-                        let trait_def_id = DefId::local(trait_id);
+                        let trait_def_id = cx.map.local_def_id(trait_id);
                         let trait_def = cx.lookup_trait_def(trait_def_id);
                         let predicates = cx.lookup_predicates(trait_def_id);
                         cx.construct_parameter_environment(trait_item.span,
@@ -1182,7 +1177,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                                            id)
                     }
                     hir::ConstTraitItem(..) => {
-                        let def_id = DefId::local(id);
+                        let def_id = cx.map.local_def_id(id);
                         let scheme = cx.lookup_item_type(def_id);
                         let predicates = cx.lookup_predicates(def_id);
                         cx.construct_parameter_environment(trait_item.span,
@@ -1195,8 +1190,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                         // block, unless this is a trait method with
                         // no default, then fallback to the method id.
                         let body_id = body.as_ref().map(|b| b.id).unwrap_or(id);
-                        let method_def_id = DefId::local(id);
-
+                        let method_def_id = cx.map.local_def_id(id);
                         match cx.impl_or_trait_item(method_def_id) {
                             MethodTraitItem(ref method_ty) => {
                                 let method_generics = &method_ty.generics;
@@ -1221,7 +1215,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                 match item.node {
                     hir::ItemFn(_, _, _, _, _, ref body) => {
                         // We assume this is a function.
-                        let fn_def_id = DefId::local(id);
+                        let fn_def_id = cx.map.local_def_id(id);
                         let fn_scheme = cx.lookup_item_type(fn_def_id);
                         let fn_predicates = cx.lookup_predicates(fn_def_id);
 
@@ -1235,7 +1229,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                     hir::ItemImpl(..) |
                     hir::ItemConst(..) |
                     hir::ItemStatic(..) => {
-                        let def_id = DefId::local(id);
+                        let def_id = cx.map.local_def_id(id);
                         let scheme = cx.lookup_item_type(def_id);
                         let predicates = cx.lookup_predicates(def_id);
                         cx.construct_parameter_environment(item.span,
@@ -1244,7 +1238,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                                            id)
                     }
                     hir::ItemTrait(..) => {
-                        let def_id = DefId::local(id);
+                        let def_id = cx.map.local_def_id(id);
                         let trait_def = cx.lookup_trait_def(def_id);
                         let predicates = cx.lookup_predicates(def_id);
                         cx.construct_parameter_environment(item.span,
@@ -1476,10 +1470,12 @@ pub type VariantDefMaster<'tcx> = &'tcx VariantDefData<'tcx, 'tcx>;
 pub type FieldDefMaster<'tcx> = &'tcx FieldDefData<'tcx, 'tcx>;
 
 pub struct VariantDefData<'tcx, 'container: 'tcx> {
+    /// The variant's DefId. If this is a tuple-like struct,
+    /// this is the DefId of the struct's ctor.
     pub did: DefId,
     pub name: Name, // struct's name if this is a struct
     pub disr_val: Disr,
-    pub fields: Vec<FieldDefData<'tcx, 'container>>
+    pub fields: Vec<FieldDefData<'tcx, 'container>>,
 }
 
 pub struct FieldDefData<'tcx, 'container: 'tcx> {
@@ -1537,7 +1533,7 @@ impl<'tcx, 'container> Hash for AdtDefData<'tcx, 'container> {
 pub enum AdtKind { Struct, Enum }
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
-pub enum VariantKind { Dict, Tuple, Unit }
+pub enum VariantKind { Struct, Tuple, Unit }
 
 impl<'tcx, 'container> AdtDefData<'tcx, 'container> {
     fn new(tcx: &ctxt<'tcx>,
@@ -1720,7 +1716,7 @@ impl<'tcx, 'container> VariantDefData<'tcx, 'container> {
             Some(&FieldDefData { name, .. }) if name == special_idents::unnamed_field.name => {
                 VariantKind::Tuple
             }
-            Some(_) => VariantKind::Dict
+            Some(_) => VariantKind::Struct
         }
     }
 
@@ -2102,21 +2098,15 @@ impl<'tcx> ctxt<'tcx> {
             hir::ExprCast(..) => {
                 false
             }
-
-            hir::ExprParen(ref e) => self.expr_is_lval(e),
         }
     }
 
-    pub fn provided_source(&self, id: DefId) -> Option<DefId> {
-        self.provided_method_sources.borrow().get(&id).cloned()
-    }
-
     pub fn provided_trait_methods(&self, id: DefId) -> Vec<Rc<Method<'tcx>>> {
-        if id.is_local() {
-            if let ItemTrait(_, _, _, ref ms) = self.map.expect_item(id.node).node {
+        if let Some(id) = self.map.as_local_node_id(id) {
+            if let ItemTrait(_, _, _, ref ms) = self.map.expect_item(id).node {
                 ms.iter().filter_map(|ti| {
                     if let hir::MethodTraitItem(_, Some(_)) = ti.node {
-                        match self.impl_or_trait_item(DefId::local(ti.id)) {
+                        match self.impl_or_trait_item(self.map.local_def_id(ti.id)) {
                             MethodTraitItem(m) => Some(m),
                             _ => {
                                 self.sess.bug("provided_trait_methods(): \
@@ -2137,12 +2127,12 @@ impl<'tcx> ctxt<'tcx> {
     }
 
     pub fn associated_consts(&self, id: DefId) -> Vec<Rc<AssociatedConst<'tcx>>> {
-        if id.is_local() {
-            match self.map.expect_item(id.node).node {
+        if let Some(id) = self.map.as_local_node_id(id) {
+            match self.map.expect_item(id).node {
                 ItemTrait(_, _, _, ref tis) => {
                     tis.iter().filter_map(|ti| {
                         if let hir::ConstTraitItem(_, _) = ti.node {
-                            match self.impl_or_trait_item(DefId::local(ti.id)) {
+                            match self.impl_or_trait_item(self.map.local_def_id(ti.id)) {
                                 ConstTraitItem(ac) => Some(ac),
                                 _ => {
                                     self.sess.bug("associated_consts(): \
@@ -2158,7 +2148,7 @@ impl<'tcx> ctxt<'tcx> {
                 ItemImpl(_, _, _, _, _, ref iis) => {
                     iis.iter().filter_map(|ii| {
                         if let hir::ConstImplItem(_, _) = ii.node {
-                            match self.impl_or_trait_item(DefId::local(ii.id)) {
+                            match self.impl_or_trait_item(self.map.local_def_id(ii.id)) {
                                 ConstTraitItem(ac) => Some(ac),
                                 _ => {
                                     self.sess.bug("associated_consts(): \
@@ -2198,8 +2188,8 @@ impl<'tcx> ctxt<'tcx> {
     }
 
     pub fn trait_impl_polarity(&self, id: DefId) -> Option<hir::ImplPolarity> {
-        if id.is_local() {
-            match self.map.find(id.node) {
+        if let Some(id) = self.map.as_local_node_id(id) {
+            match self.map.find(id) {
                 Some(ast_map::NodeItem(item)) => {
                     match item.node {
                         hir::ItemImpl(_, polarity, _, _, _, _) => Some(polarity),
@@ -2254,9 +2244,9 @@ impl<'tcx> ctxt<'tcx> {
 
     /// Returns whether this DefId refers to an impl
     pub fn is_impl(&self, id: DefId) -> bool {
-        if id.is_local() {
+        if let Some(id) = self.map.as_local_node_id(id) {
             if let Some(ast_map::NodeItem(
-                &hir::Item { node: hir::ItemImpl(..), .. })) = self.map.find(id.node) {
+                &hir::Item { node: hir::ItemImpl(..), .. })) = self.map.find(id) {
                 true
             } else {
                 false
@@ -2274,19 +2264,27 @@ impl<'tcx> ctxt<'tcx> {
         self.with_path(id, |path| ast_map::path_to_string(path))
     }
 
+    pub fn def_path(&self, id: DefId) -> ast_map::DefPath {
+        if id.is_local() {
+            self.map.def_path(id)
+        } else {
+            csearch::def_path(self, id)
+        }
+    }
+
     pub fn with_path<T, F>(&self, id: DefId, f: F) -> T where
         F: FnOnce(ast_map::PathElems) -> T,
     {
-        if id.is_local() {
-            self.map.with_path(id.node, f)
+        if let Some(id) = self.map.as_local_node_id(id) {
+            self.map.with_path(id, f)
         } else {
             f(csearch::get_item_path(self, id).iter().cloned().chain(LinkedPath::empty()))
         }
     }
 
     pub fn item_name(&self, id: DefId) -> ast::Name {
-        if id.is_local() {
-            self.map.get_path_elem(id.node).name()
+        if let Some(id) = self.map.as_local_node_id(id) {
+            self.map.get_path_elem(id).name()
         } else {
             csearch::get_item_name(self, id)
         }
@@ -2345,9 +2343,9 @@ impl<'tcx> ctxt<'tcx> {
     }
 
     /// Get the attributes of a definition.
-    pub fn get_attrs(&self, did: DefId) -> Cow<'tcx, [hir::Attribute]> {
-        if did.is_local() {
-            Cow::Borrowed(self.map.attrs(did.node))
+    pub fn get_attrs(&self, did: DefId) -> Cow<'tcx, [ast::Attribute]> {
+        if let Some(id) = self.map.as_local_node_id(did) {
+            Cow::Borrowed(self.map.attrs(id))
         } else {
             Cow::Owned(csearch::get_item_attrs(&self.sess.cstore, did))
         }
@@ -2479,16 +2477,9 @@ impl<'tcx> ctxt<'tcx> {
             // the map. This is a bit unfortunate.
             for impl_item_def_id in &impl_items {
                 let method_def_id = impl_item_def_id.def_id();
-                match self.impl_or_trait_item(method_def_id) {
-                    MethodTraitItem(method) => {
-                        if let Some(source) = method.provided_source {
-                            self.provided_method_sources
-                                .borrow_mut()
-                                .insert(method_def_id, source);
-                        }
-                    }
-                    _ => {}
-                }
+                // load impl items eagerly for convenience
+                // FIXME: we may want to load these lazily
+                self.impl_or_trait_item(method_def_id);
             }
 
             // Store the implementation info.
@@ -2498,6 +2489,18 @@ impl<'tcx> ctxt<'tcx> {
         def.flags.set(def.flags.get() | TraitFlags::IMPLS_VALID);
     }
 
+    pub fn closure_kind(&self, def_id: DefId) -> ty::ClosureKind {
+        Tables::closure_kind(&self.tables, self, def_id)
+    }
+
+    pub fn closure_type(&self,
+                        def_id: DefId,
+                        substs: &ClosureSubsts<'tcx>)
+                        -> ty::ClosureTy<'tcx>
+    {
+        Tables::closure_type(&self.tables, self, def_id, substs)
+    }
+
     /// Given the def_id of an impl, return the def_id of the trait it implements.
     /// If it implements no trait, return `None`.
     pub fn trait_id_of_impl(&self, def_id: DefId) -> Option<DefId> {
index 4ed87e673d99682f3efd3ea72754492ea6dc8da8..176dc5a743d05a15e87f3f00c8b883221c9a70e1 100644 (file)
@@ -417,7 +417,9 @@ impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>> Lift<'tcx> for (A, B) {
 impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for [T] {
     type Lifted = Vec<T::Lifted>;
     fn lift_to_tcx(&self, tcx: &ty::ctxt<'tcx>) -> Option<Self::Lifted> {
-        let mut result = Vec::with_capacity(self.len());
+        // type annotation needed to inform `projection_must_outlive`
+        let mut result : Vec<<T as Lift<'tcx>>::Lifted>
+            = Vec::with_capacity(self.len());
         for x in self {
             if let Some(value) = tcx.lift(x) {
                 result.push(value);
index 3969738a22e86b94278bb4042612ff9065ddd506..37ed716eaa0b828411452ae587b5b5af45d0bda1 100644 (file)
@@ -23,7 +23,7 @@ use std::fmt;
 use std::ops;
 use std::mem;
 use syntax::abi;
-use syntax::ast::{Name, NodeId};
+use syntax::ast::{self, Name};
 use syntax::parse::token::special_idents;
 
 use rustc_front::hir;
@@ -79,13 +79,13 @@ pub enum TypeVariants<'tcx> {
     TyChar,
 
     /// A primitive signed integer type. For example, `i32`.
-    TyInt(hir::IntTy),
+    TyInt(ast::IntTy),
 
     /// A primitive unsigned integer type. For example, `u32`.
-    TyUint(hir::UintTy),
+    TyUint(ast::UintTy),
 
     /// A primitive floating-point type. For example, `f64`.
-    TyFloat(hir::FloatTy),
+    TyFloat(ast::FloatTy),
 
     /// An enumerated type, defined with `enum`.
     ///
@@ -93,7 +93,7 @@ pub enum TypeVariants<'tcx> {
     /// That is, even after substitution it is possible that there are type
     /// variables. This happens when the `TyEnum` corresponds to an enum
     /// definition and not a concrete use of it. To get the correct `TyEnum`
-    /// from the tcx, use the `NodeId` from the `hir::Ty` and look it up in
+    /// from the tcx, use the `NodeId` from the `ast::Ty` and look it up in
     /// the `ast_ty_to_ty_cache`. This is probably true for `TyStruct` as
     /// well.
     TyEnum(AdtDef<'tcx>, &'tcx Substs<'tcx>),
@@ -126,7 +126,7 @@ pub enum TypeVariants<'tcx> {
     TyRef(&'tcx Region, TypeAndMut<'tcx>),
 
     /// If the def-id is Some(_), then this is the type of a specific
-    /// fn item. Otherwise, if None(_), it a fn pointer type.
+    /// fn item. Otherwise, if None(_), it is a fn pointer type.
     ///
     /// FIXME: Conflating function pointers and the type of a
     /// function is probably a terrible idea; a function pointer is a
@@ -675,7 +675,7 @@ pub enum Region {
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
 pub struct EarlyBoundRegion {
-    pub param_id: NodeId,
+    pub def_id: DefId,
     pub space: subst::ParamSpace,
     pub index: u32,
     pub name: Name,
@@ -899,6 +899,14 @@ impl<'tcx> TyS<'tcx> {
         }
     }
 
+    pub fn is_phantom_data(&self) -> bool {
+        if let TyStruct(def, _) = self.sty {
+            def.is_phantom_data()
+        } else {
+            false
+        }
+    }
+
     pub fn is_bool(&self) -> bool { self.sty == TyBool }
 
     pub fn is_param(&self, space: subst::ParamSpace, index: u32) -> bool {
@@ -944,7 +952,7 @@ impl<'tcx> TyS<'tcx> {
     pub fn sequence_element_type(&self, cx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
         match self.sty {
             TyArray(ty, _) | TySlice(ty) => ty,
-            TyStr => cx.mk_mach_uint(hir::TyU8),
+            TyStr => cx.mk_mach_uint(ast::TyU8),
             _ => cx.sess.bug(&format!("sequence_element_type called on non-sequence value: {}",
                                       self)),
         }
@@ -1035,7 +1043,7 @@ impl<'tcx> TyS<'tcx> {
 
     pub fn is_uint(&self) -> bool {
         match self.sty {
-            TyInfer(IntVar(_)) | TyUint(hir::TyUs) => true,
+            TyInfer(IntVar(_)) | TyUint(ast::TyUs) => true,
             _ => false
         }
     }
@@ -1081,7 +1089,7 @@ impl<'tcx> TyS<'tcx> {
 
     pub fn is_machine(&self) -> bool {
         match self.sty {
-            TyInt(hir::TyIs) | TyUint(hir::TyUs) => false,
+            TyInt(ast::TyIs) | TyUint(ast::TyUs) => false,
             TyInt(..) | TyUint(..) | TyFloat(..) => true,
             _ => false
         }
index 883146185357610d07635437095106548b24a59f..2142755d4a59e87e6b3796f3eb6d607b56cad9f3 100644 (file)
@@ -14,7 +14,7 @@ use back::svh::Svh;
 use middle::const_eval::{self, ConstVal, ErrKind};
 use middle::const_eval::EvalHint::UncheckedExprHint;
 use middle::def_id::DefId;
-use middle::subst;
+use middle::subst::{self, Subst, Substs};
 use middle::infer;
 use middle::pat_util;
 use middle::traits;
@@ -26,11 +26,12 @@ use util::num::ToPrimitive;
 
 use std::cmp;
 use std::hash::{Hash, SipHasher, Hasher};
-use syntax::ast::Name;
+use std::rc::Rc;
+use syntax::ast::{self, Name};
+use syntax::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt};
 use syntax::codemap::Span;
 
 use rustc_front::hir;
-use rustc_front::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt};
 
 pub trait IntTypeExt {
     fn to_ty<'tcx>(&self, cx: &ty::ctxt<'tcx>) -> Ty<'tcx>;
@@ -44,48 +45,48 @@ pub trait IntTypeExt {
 impl IntTypeExt for attr::IntType {
     fn to_ty<'tcx>(&self, cx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
         match *self {
-            SignedInt(hir::TyI8)      => cx.types.i8,
-            SignedInt(hir::TyI16)     => cx.types.i16,
-            SignedInt(hir::TyI32)     => cx.types.i32,
-            SignedInt(hir::TyI64)     => cx.types.i64,
-            SignedInt(hir::TyIs)   => cx.types.isize,
-            UnsignedInt(hir::TyU8)    => cx.types.u8,
-            UnsignedInt(hir::TyU16)   => cx.types.u16,
-            UnsignedInt(hir::TyU32)   => cx.types.u32,
-            UnsignedInt(hir::TyU64)   => cx.types.u64,
-            UnsignedInt(hir::TyUs) => cx.types.usize,
+            SignedInt(ast::TyI8)      => cx.types.i8,
+            SignedInt(ast::TyI16)     => cx.types.i16,
+            SignedInt(ast::TyI32)     => cx.types.i32,
+            SignedInt(ast::TyI64)     => cx.types.i64,
+            SignedInt(ast::TyIs)   => cx.types.isize,
+            UnsignedInt(ast::TyU8)    => cx.types.u8,
+            UnsignedInt(ast::TyU16)   => cx.types.u16,
+            UnsignedInt(ast::TyU32)   => cx.types.u32,
+            UnsignedInt(ast::TyU64)   => cx.types.u64,
+            UnsignedInt(ast::TyUs) => cx.types.usize,
         }
     }
 
     fn i64_to_disr(&self, val: i64) -> Option<Disr> {
         match *self {
-            SignedInt(hir::TyI8)    => val.to_i8()  .map(|v| v as Disr),
-            SignedInt(hir::TyI16)   => val.to_i16() .map(|v| v as Disr),
-            SignedInt(hir::TyI32)   => val.to_i32() .map(|v| v as Disr),
-            SignedInt(hir::TyI64)   => val.to_i64() .map(|v| v as Disr),
-            UnsignedInt(hir::TyU8)  => val.to_u8()  .map(|v| v as Disr),
-            UnsignedInt(hir::TyU16) => val.to_u16() .map(|v| v as Disr),
-            UnsignedInt(hir::TyU32) => val.to_u32() .map(|v| v as Disr),
-            UnsignedInt(hir::TyU64) => val.to_u64() .map(|v| v as Disr),
-
-            UnsignedInt(hir::TyUs) |
-            SignedInt(hir::TyIs) => unreachable!(),
+            SignedInt(ast::TyI8)    => val.to_i8()  .map(|v| v as Disr),
+            SignedInt(ast::TyI16)   => val.to_i16() .map(|v| v as Disr),
+            SignedInt(ast::TyI32)   => val.to_i32() .map(|v| v as Disr),
+            SignedInt(ast::TyI64)   => val.to_i64() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU8)  => val.to_u8()  .map(|v| v as Disr),
+            UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr),
+
+            UnsignedInt(ast::TyUs) |
+            SignedInt(ast::TyIs) => unreachable!(),
         }
     }
 
     fn u64_to_disr(&self, val: u64) -> Option<Disr> {
         match *self {
-            SignedInt(hir::TyI8)    => val.to_i8()  .map(|v| v as Disr),
-            SignedInt(hir::TyI16)   => val.to_i16() .map(|v| v as Disr),
-            SignedInt(hir::TyI32)   => val.to_i32() .map(|v| v as Disr),
-            SignedInt(hir::TyI64)   => val.to_i64() .map(|v| v as Disr),
-            UnsignedInt(hir::TyU8)  => val.to_u8()  .map(|v| v as Disr),
-            UnsignedInt(hir::TyU16) => val.to_u16() .map(|v| v as Disr),
-            UnsignedInt(hir::TyU32) => val.to_u32() .map(|v| v as Disr),
-            UnsignedInt(hir::TyU64) => val.to_u64() .map(|v| v as Disr),
-
-            UnsignedInt(hir::TyUs) |
-            SignedInt(hir::TyIs) => unreachable!(),
+            SignedInt(ast::TyI8)    => val.to_i8()  .map(|v| v as Disr),
+            SignedInt(ast::TyI16)   => val.to_i16() .map(|v| v as Disr),
+            SignedInt(ast::TyI32)   => val.to_i32() .map(|v| v as Disr),
+            SignedInt(ast::TyI64)   => val.to_i64() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU8)  => val.to_u8()  .map(|v| v as Disr),
+            UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr),
+
+            UnsignedInt(ast::TyUs) |
+            SignedInt(ast::TyIs) => unreachable!(),
         }
     }
 
@@ -97,18 +98,18 @@ impl IntTypeExt for attr::IntType {
             // SignedInt repr means we *want* to reinterpret the bits
             // treating the highest bit of Disr as a sign-bit, so
             // cast to i64 before range-checking.
-            SignedInt(hir::TyI8)    => add1!((val as i64).to_i8()),
-            SignedInt(hir::TyI16)   => add1!((val as i64).to_i16()),
-            SignedInt(hir::TyI32)   => add1!((val as i64).to_i32()),
-            SignedInt(hir::TyI64)   => add1!(Some(val as i64)),
-
-            UnsignedInt(hir::TyU8)  => add1!(val.to_u8()),
-            UnsignedInt(hir::TyU16) => add1!(val.to_u16()),
-            UnsignedInt(hir::TyU32) => add1!(val.to_u32()),
-            UnsignedInt(hir::TyU64) => add1!(Some(val)),
-
-            UnsignedInt(hir::TyUs) |
-            SignedInt(hir::TyIs) => unreachable!(),
+            SignedInt(ast::TyI8)    => add1!((val as i64).to_i8()),
+            SignedInt(ast::TyI16)   => add1!((val as i64).to_i16()),
+            SignedInt(ast::TyI32)   => add1!((val as i64).to_i32()),
+            SignedInt(ast::TyI64)   => add1!(Some(val as i64)),
+
+            UnsignedInt(ast::TyU8)  => add1!(val.to_u8()),
+            UnsignedInt(ast::TyU16) => add1!(val.to_u16()),
+            UnsignedInt(ast::TyU32) => add1!(val.to_u32()),
+            UnsignedInt(ast::TyU64) => add1!(Some(val)),
+
+            UnsignedInt(ast::TyUs) |
+            SignedInt(ast::TyIs) => unreachable!(),
         }
     }
 
@@ -117,17 +118,17 @@ impl IntTypeExt for attr::IntType {
     // full range from `i64::MIN` through `u64::MAX`.
     fn disr_string(&self, val: Disr) -> String {
         match *self {
-            SignedInt(hir::TyI8)    => format!("{}", val as i8 ),
-            SignedInt(hir::TyI16)   => format!("{}", val as i16),
-            SignedInt(hir::TyI32)   => format!("{}", val as i32),
-            SignedInt(hir::TyI64)   => format!("{}", val as i64),
-            UnsignedInt(hir::TyU8)  => format!("{}", val as u8 ),
-            UnsignedInt(hir::TyU16) => format!("{}", val as u16),
-            UnsignedInt(hir::TyU32) => format!("{}", val as u32),
-            UnsignedInt(hir::TyU64) => format!("{}", val as u64),
-
-            UnsignedInt(hir::TyUs) |
-            SignedInt(hir::TyIs) => unreachable!(),
+            SignedInt(ast::TyI8)    => format!("{}", val as i8 ),
+            SignedInt(ast::TyI16)   => format!("{}", val as i16),
+            SignedInt(ast::TyI32)   => format!("{}", val as i32),
+            SignedInt(ast::TyI64)   => format!("{}", val as i64),
+            UnsignedInt(ast::TyU8)  => format!("{}", val as u8 ),
+            UnsignedInt(ast::TyU16) => format!("{}", val as u16),
+            UnsignedInt(ast::TyU32) => format!("{}", val as u32),
+            UnsignedInt(ast::TyU64) => format!("{}", val as u64),
+
+            UnsignedInt(ast::TyUs) |
+            SignedInt(ast::TyIs) => unreachable!(),
         }
     }
 
@@ -137,17 +138,17 @@ impl IntTypeExt for attr::IntType {
         }
         let val = val.unwrap_or(ty::INITIAL_DISCRIMINANT_VALUE);
         match *self {
-            SignedInt(hir::TyI8)    => add1!(val as i8 ),
-            SignedInt(hir::TyI16)   => add1!(val as i16),
-            SignedInt(hir::TyI32)   => add1!(val as i32),
-            SignedInt(hir::TyI64)   => add1!(val as i64),
-            UnsignedInt(hir::TyU8)  => add1!(val as u8 ),
-            UnsignedInt(hir::TyU16) => add1!(val as u16),
-            UnsignedInt(hir::TyU32) => add1!(val as u32),
-            UnsignedInt(hir::TyU64) => add1!(val as u64),
-
-            UnsignedInt(hir::TyUs) |
-            SignedInt(hir::TyIs) => unreachable!(),
+            SignedInt(ast::TyI8)    => add1!(val as i8 ),
+            SignedInt(ast::TyI16)   => add1!(val as i16),
+            SignedInt(ast::TyI32)   => add1!(val as i32),
+            SignedInt(ast::TyI64)   => add1!(val as i64),
+            UnsignedInt(ast::TyU8)  => add1!(val as u8 ),
+            UnsignedInt(ast::TyU16) => add1!(val as u16),
+            UnsignedInt(ast::TyU32) => add1!(val as u32),
+            UnsignedInt(ast::TyU64) => add1!(val as u64),
+
+            UnsignedInt(ast::TyUs) |
+            SignedInt(ast::TyIs) => unreachable!(),
         }
     }
 }
@@ -279,14 +280,14 @@ impl<'tcx> ty::ctxt<'tcx> {
             //
             // NB. Historically `fn enum_variants` generate i64 here, while
             // rustc_typeck::check would generate isize.
-            _ => SignedInt(hir::TyIs),
+            _ => SignedInt(ast::TyIs),
         };
 
         let repr_type_ty = repr_type.to_ty(self);
         let repr_type = match repr_type {
-            SignedInt(hir::TyIs) =>
+            SignedInt(ast::TyIs) =>
                 SignedInt(self.sess.target.int_type),
-            UnsignedInt(hir::TyUs) =>
+            UnsignedInt(ast::TyUs) =>
                 UnsignedInt(self.sess.target.uint_type),
             other => other
         };
@@ -334,7 +335,7 @@ impl<'tcx> ty::ctxt<'tcx> {
     /// Returns the repeat count for a repeating vector expression.
     pub fn eval_repeat_count(&self, count_expr: &hir::Expr) -> usize {
         let hint = UncheckedExprHint(self.types.usize);
-        match const_eval::eval_const_expr_partial(self, count_expr, hint) {
+        match const_eval::eval_const_expr_partial(self, count_expr, hint, None) {
             Ok(val) => {
                 let found = match val {
                     ConstVal::Uint(count) => return count as usize,
@@ -460,7 +461,7 @@ impl<'tcx> ty::ctxt<'tcx> {
                     tcx.sess.cstore.get_crate_hash(did.krate)
                 };
                 h.as_str().hash(state);
-                did.node.hash(state);
+                did.index.hash(state);
             };
             let mt = |state: &mut SipHasher, mt: TypeAndMut| {
                 mt.mutbl.hash(state);
@@ -565,84 +566,86 @@ impl<'tcx> ty::ctxt<'tcx> {
         }
     }
 
-    /// Returns true if this ADT is a dtorck type, i.e. whether it being
-    /// safe for destruction requires it to be alive
+    /// Returns true if this ADT is a dtorck type.
+    ///
+    /// Invoking the destructor of a dtorck type during usual cleanup
+    /// (e.g. the glue emitted for stack unwinding) requires all
+    /// lifetimes in the type-structure of `adt` to strictly outlive
+    /// the adt value itself.
+    ///
+    /// If `adt` is not dtorck, then the adt's destructor can be
+    /// invoked even when there are lifetimes in the type-structure of
+    /// `adt` that do not strictly outlive the adt value itself.
+    /// (This allows programs to make cyclic structures without
+    /// resorting to unasfe means; see RFCs 769 and 1238).
     pub fn is_adt_dtorck(&self, adt: ty::AdtDef<'tcx>) -> bool {
         let dtor_method = match adt.destructor() {
             Some(dtor) => dtor,
             None => return false
         };
-        let impl_did = self.impl_of_method(dtor_method).unwrap_or_else(|| {
-            self.sess.bug(&format!("no Drop impl for the dtor of `{:?}`", adt))
-        });
-        let generics = adt.type_scheme(self).generics;
-
-        // In `impl<'a> Drop ...`, we automatically assume
-        // `'a` is meaningful and thus represents a bound
-        // through which we could reach borrowed data.
+
+        // RFC 1238: if the destructor method is tagged with the
+        // attribute `unsafe_destructor_blind_to_params`, then the
+        // compiler is being instructed to *assume* that the
+        // destructor will not access borrowed data,
+        // even if such data is otherwise reachable.
         //
-        // FIXME (pnkfelix): In the future it would be good to
-        // extend the language to allow the user to express,
-        // in the impl signature, that a lifetime is not
-        // actually used (something like `where 'a: ?Live`).
-        if generics.has_region_params(subst::TypeSpace) {
-            debug!("typ: {:?} has interesting dtor due to region params",
-                   adt);
-            return true;
-        }
+        // Such access can be in plain sight (e.g. dereferencing
+        // `*foo.0` of `Foo<'a>(&'a u32)`) or indirectly hidden
+        // (e.g. calling `foo.0.clone()` of `Foo<T:Clone>`).
+        return !self.has_attr(dtor_method, "unsafe_destructor_blind_to_params");
+    }
+}
 
-        let mut seen_items = Vec::new();
-        let mut items_to_inspect = vec![impl_did];
-        while let Some(item_def_id) = items_to_inspect.pop() {
-            if seen_items.contains(&item_def_id) {
-                continue;
-            }
+#[derive(Debug)]
+pub struct ImplMethod<'tcx> {
+    pub method: Rc<ty::Method<'tcx>>,
+    pub substs: Substs<'tcx>,
+    pub is_provided: bool
+}
 
-            for pred in self.lookup_predicates(item_def_id).predicates {
-                let result = match pred {
-                    ty::Predicate::Equate(..) |
-                    ty::Predicate::RegionOutlives(..) |
-                    ty::Predicate::TypeOutlives(..) |
-                    ty::Predicate::WellFormed(..) |
-                    ty::Predicate::ObjectSafe(..) |
-                    ty::Predicate::Projection(..) => {
-                        // For now, assume all these where-clauses
-                        // may give drop implementation capabilty
-                        // to access borrowed data.
-                        true
+impl<'tcx> ty::ctxt<'tcx> {
+    #[inline(never)] // is this perfy enough?
+    pub fn get_impl_method(&self,
+                           impl_def_id: DefId,
+                           substs: Substs<'tcx>,
+                           name: Name)
+                           -> ImplMethod<'tcx>
+    {
+        // there don't seem to be nicer accessors to these:
+        let impl_or_trait_items_map = self.impl_or_trait_items.borrow();
+
+        for impl_item in &self.impl_items.borrow()[&impl_def_id] {
+            if let ty::MethodTraitItem(ref meth) =
+                impl_or_trait_items_map[&impl_item.def_id()] {
+                if meth.name == name {
+                    return ImplMethod {
+                        method: meth.clone(),
+                        substs: substs,
+                        is_provided: false
                     }
+                }
+            }
+        }
 
-                    ty::Predicate::Trait(ty::Binder(ref t_pred)) => {
-                        let def_id = t_pred.trait_ref.def_id;
-                        if self.trait_items(def_id).len() != 0 {
-                            // If trait has items, assume it adds
-                            // capability to access borrowed data.
-                            true
-                        } else {
-                            // Trait without items is itself
-                            // uninteresting from POV of dropck.
-                            //
-                            // However, may have parent w/ items;
-                            // so schedule checking of predicates,
-                            items_to_inspect.push(def_id);
-                            // and say "no capability found" for now.
-                            false
-                        }
+        // It is not in the impl - get the default from the trait.
+        let trait_ref = self.impl_trait_ref(impl_def_id).unwrap();
+        for trait_item in self.trait_items(trait_ref.def_id).iter() {
+            if let &ty::MethodTraitItem(ref meth) = trait_item {
+                if meth.name == name {
+                    let impl_to_trait_substs = self
+                        .make_substs_for_receiver_types(&trait_ref, meth);
+                    return ImplMethod {
+                        method: meth.clone(),
+                        substs: impl_to_trait_substs.subst(self, &substs),
+                        is_provided: true
                     }
-                };
-
-                if result {
-                    debug!("typ: {:?} has interesting dtor due to generic preds, e.g. {:?}",
-                           adt, pred);
-                    return true;
                 }
             }
-
-            seen_items.push(item_def_id);
         }
 
-        debug!("typ: {:?} is dtorck-safe", adt);
-        false
+        self.sess.bug(&format!("method {:?} not found in {:?}",
+                               name, impl_def_id))
     }
 }
 
index 43b7943fd2096f88bf999fa5d5583574a01269b6..96c8e5c7d5218cddbf35bc9536604b3b3d60cff4 100644 (file)
@@ -15,6 +15,7 @@ use session::Session;
 use metadata::csearch;
 use middle::lang_items;
 
+use syntax::ast;
 use syntax::codemap::Span;
 use syntax::parse::token::InternedString;
 use rustc_front::visit::Visitor;
@@ -54,7 +55,7 @@ pub fn check_crate(krate: &hir::Crate,
     verify(sess, items);
 }
 
-pub fn link_name(attrs: &[hir::Attribute]) -> Option<InternedString> {
+pub fn link_name(attrs: &[ast::Attribute]) -> Option<InternedString> {
     lang_items::extract(attrs).and_then(|name| {
         $(if &name[..] == stringify!($name) {
             Some(InternedString::new(stringify!($sym)))
index 55fd63b7534721a4943d16c6572c24e314ae85f5..ea85b264261cd2d7027e3b7d2753be4700940674 100644 (file)
 //! Used by `rustc` when compiling a plugin crate.
 
 use syntax::ast;
+use syntax::attr;
 use syntax::codemap::Span;
 use syntax::diagnostic;
 use rustc_front::visit;
 use rustc_front::visit::Visitor;
 use rustc_front::hir;
-use rustc_front::attr;
 
 struct RegistrarFinder {
     registrars: Vec<(ast::NodeId, Span)> ,
index e0cb47d6c952378b8a63847d272b48ee482aaf16..751e748094d02b9ce55cf3300ecb134da40fe4e2 100644 (file)
@@ -15,7 +15,6 @@ use metadata::creader::CrateReader;
 use plugin::registry::Registry;
 
 use std::borrow::ToOwned;
-use std::dynamic_lib::DynamicLibrary;
 use std::env;
 use std::mem;
 use std::path::PathBuf;
@@ -39,6 +38,10 @@ struct PluginLoader<'a> {
     plugins: Vec<PluginRegistrar>,
 }
 
+fn call_malformed_plugin_attribute(a: &Session, b: Span) {
+    span_err!(a, b, E0498, "malformed plugin attribute");
+}
+
 /// Read plugin metadata and dynamically load registrar functions.
 pub fn load_plugins(sess: &Session, krate: &ast::Crate,
                     addl_plugins: Option<Vec<String>>) -> Vec<PluginRegistrar> {
@@ -52,14 +55,14 @@ pub fn load_plugins(sess: &Session, krate: &ast::Crate,
         let plugins = match attr.meta_item_list() {
             Some(xs) => xs,
             None => {
-                sess.span_err(attr.span, "malformed plugin attribute");
+                call_malformed_plugin_attribute(sess, attr.span);
                 continue;
             }
         };
 
         for plugin in plugins {
             if plugin.value_str().is_some() {
-                sess.span_err(attr.span, "malformed plugin attribute");
+                call_malformed_plugin_attribute(sess, attr.span);
                 continue;
             }
 
@@ -99,10 +102,13 @@ impl<'a> PluginLoader<'a> {
     }
 
     // Dynamically link a registrar function into the compiler process.
+    #[allow(deprecated)]
     fn dylink_registrar(&mut self,
                         span: Span,
                         path: PathBuf,
                         symbol: String) -> PluginRegistrarFun {
+        use std::dynamic_lib::DynamicLibrary;
+
         // Make sure the path contains a / or the linker will search for it.
         let path = env::current_dir().unwrap().join(&path);
 
index e79721b4347a6e6d03e7bdd8b3ff1f2f8b97a421..50ca092dfe64e43e5e694c004544de673a477342 100644 (file)
@@ -10,7 +10,7 @@
 
 //! Used by plugin crates to tell `rustc` about the plugins they provide.
 
-use lint::{LintPassObject, LintId, Lint};
+use lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint};
 use session::Session;
 
 use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
@@ -48,7 +48,10 @@ pub struct Registry<'a> {
     pub syntax_exts: Vec<NamedSyntaxExtension>,
 
     #[doc(hidden)]
-    pub lint_passes: Vec<LintPassObject>,
+    pub early_lint_passes: Vec<EarlyLintPassObject>,
+
+    #[doc(hidden)]
+    pub late_lint_passes: Vec<LateLintPassObject>,
 
     #[doc(hidden)]
     pub lint_groups: HashMap<&'static str, Vec<LintId>>,
@@ -68,7 +71,8 @@ impl<'a> Registry<'a> {
             args_hidden: None,
             krate_span: krate.span,
             syntax_exts: vec!(),
-            lint_passes: vec!(),
+            early_lint_passes: vec!(),
+            late_lint_passes: vec!(),
             lint_groups: HashMap::new(),
             llvm_passes: vec!(),
             attributes: vec!(),
@@ -89,7 +93,6 @@ impl<'a> Registry<'a> {
     /// Register a syntax extension of any kind.
     ///
     /// This is the most general hook into `libsyntax`'s expansion behavior.
-    #[allow(deprecated)]
     pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) {
         self.syntax_exts.push((name, match extension {
             NormalTT(ext, _, allow_internal_unstable) => {
@@ -118,10 +121,14 @@ impl<'a> Registry<'a> {
     }
 
     /// Register a compiler lint pass.
-    pub fn register_lint_pass(&mut self, lint_pass: LintPassObject) {
-        self.lint_passes.push(lint_pass);
+    pub fn register_early_lint_pass(&mut self, lint_pass: EarlyLintPassObject) {
+        self.early_lint_passes.push(lint_pass);
     }
 
+    /// Register a compiler lint pass.
+    pub fn register_late_lint_pass(&mut self, lint_pass: LateLintPassObject) {
+        self.late_lint_passes.push(lint_pass);
+    }
     /// Register a lint group.
     pub fn register_lint_group(&mut self, name: &'static str, to: Vec<&'static Lint>) {
         self.lint_groups.insert(name, to.into_iter().map(|x| LintId::of(x)).collect());
index b56283e756723c965fd8c7ccfef15d7bc1755096..7e8104d08d68381541a6125d19f424c13452ce5e 100644 (file)
@@ -15,7 +15,6 @@ pub use self::EntryFnType::*;
 pub use self::CrateType::*;
 pub use self::Passes::*;
 pub use self::OptLevel::*;
-pub use self::OutputType::*;
 pub use self::DebugInfoLevel::*;
 
 use session::{early_error, early_warn, Session};
@@ -25,11 +24,9 @@ use rustc_back::target::Target;
 use lint;
 use metadata::cstore;
 
-use syntax::ast;
-use rustc_front::hir::{IntTy, UintTy};
+use syntax::ast::{self, IntTy, UintTy};
 use syntax::attr;
 use syntax::attr::AttrMetaMethods;
-use rustc_front::hir;
 use syntax::diagnostic::{ColorConfig, Auto, Always, Never, SpanHandler};
 use syntax::parse;
 use syntax::parse::token::InternedString;
@@ -64,14 +61,14 @@ pub enum DebugInfoLevel {
     FullDebugInfo,
 }
 
-#[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub enum OutputType {
-    OutputTypeBitcode,
-    OutputTypeAssembly,
-    OutputTypeLlvmAssembly,
-    OutputTypeObject,
-    OutputTypeExe,
-    OutputTypeDepInfo,
+    Bitcode,
+    Assembly,
+    LlvmAssembly,
+    Object,
+    Exe,
+    DepInfo,
 }
 
 #[derive(Clone)]
@@ -87,7 +84,7 @@ pub struct Options {
     pub lint_opts: Vec<(String, lint::Level)>,
     pub lint_cap: Option<lint::Level>,
     pub describe_lints: bool,
-    pub output_types: Vec<OutputType>,
+    pub output_types: HashMap<OutputType, Option<PathBuf>>,
     // This was mutable for rustpkg, which updates search paths based on the
     // parsed code. It remains mutable in case its replacements wants to use
     // this.
@@ -104,11 +101,8 @@ pub struct Options {
     pub parse_only: bool,
     pub no_trans: bool,
     pub treat_err_as_bug: bool,
-    pub always_build_mir: bool,
     pub no_analysis: bool,
     pub debugging_opts: DebuggingOptions,
-    /// Whether to write dependency files. It's (enabled, optional filename).
-    pub write_dependency_info: (bool, Option<PathBuf>),
     pub prints: Vec<PrintRequest>,
     pub cg: CodegenOptions,
     pub color: ColorConfig,
@@ -153,26 +147,25 @@ pub struct OutputFilenames {
     pub out_filestem: String,
     pub single_output_file: Option<PathBuf>,
     pub extra: String,
+    pub outputs: HashMap<OutputType, Option<PathBuf>>,
 }
 
 impl OutputFilenames {
     pub fn path(&self, flavor: OutputType) -> PathBuf {
-        match self.single_output_file {
-            Some(ref path) => return path.clone(),
-            None => {}
-        }
-        self.temp_path(flavor)
+        self.outputs.get(&flavor).and_then(|p| p.to_owned())
+            .or_else(|| self.single_output_file.clone())
+            .unwrap_or_else(|| self.temp_path(flavor))
     }
 
     pub fn temp_path(&self, flavor: OutputType) -> PathBuf {
         let base = self.out_directory.join(&self.filestem());
         match flavor {
-            OutputTypeBitcode => base.with_extension("bc"),
-            OutputTypeAssembly => base.with_extension("s"),
-            OutputTypeLlvmAssembly => base.with_extension("ll"),
-            OutputTypeObject => base.with_extension("o"),
-            OutputTypeDepInfo => base.with_extension("d"),
-            OutputTypeExe => base,
+            OutputType::Bitcode => base.with_extension("bc"),
+            OutputType::Assembly => base.with_extension("s"),
+            OutputType::LlvmAssembly => base.with_extension("ll"),
+            OutputType::Object => base.with_extension("o"),
+            OutputType::DepInfo => base.with_extension("d"),
+            OutputType::Exe => base,
         }
     }
 
@@ -208,7 +201,7 @@ pub fn basic_options() -> Options {
         lint_opts: Vec::new(),
         lint_cap: None,
         describe_lints: false,
-        output_types: Vec::new(),
+        output_types: HashMap::new(),
         search_paths: SearchPaths::new(),
         maybe_sysroot: None,
         target_triple: host_triple().to_string(),
@@ -217,10 +210,8 @@ pub fn basic_options() -> Options {
         parse_only: false,
         no_trans: false,
         treat_err_as_bug: false,
-        always_build_mir: false,
         no_analysis: false,
         debugging_opts: basic_debugging_options(),
-        write_dependency_info: (false, None),
         prints: Vec::new(),
         cg: basic_codegen_options(),
         color: Auto,
@@ -585,8 +576,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
           "Run all passes except translation; no output"),
     treat_err_as_bug: bool = (false, parse_bool,
           "Treat all errors that occur as bugs"),
-    always_build_mir: bool = (false, parse_bool,
-          "Always build MIR for all fns, even without a #[rustc_mir] annotation"),
     no_analysis: bool = (false, parse_bool,
           "Parse and expand the source, but run no analysis"),
     extra_plugins: Vec<String> = (Vec::new(), parse_list,
@@ -603,6 +592,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
           "For every macro invocation, print its name and arguments"),
     enable_nonzeroing_move_hints: bool = (false, parse_bool,
           "Force nonzeroing move optimization on"),
+    keep_mtwt_tables: bool = (false, parse_bool,
+          "Don't clear the resolution tables after analysis"),
 }
 
 pub fn default_lib_output() -> CrateType {
@@ -617,6 +608,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
     let wordsz = &sess.target.target.target_pointer_width;
     let os = &sess.target.target.target_os;
     let env = &sess.target.target.target_env;
+    let vendor = &sess.target.target.target_vendor;
 
     let fam = match sess.target.target.options.is_like_windows {
         true  => InternedString::new("windows"),
@@ -632,6 +624,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
          mk(InternedString::new("target_endian"), intern(end)),
          mk(InternedString::new("target_pointer_width"), intern(wordsz)),
          mk(InternedString::new("target_env"), intern(env)),
+         mk(InternedString::new("target_vendor"), intern(vendor)),
     ];
     if sess.opts.debug_assertions {
         ret.push(attr::mk_word_item(InternedString::new("debug_assertions")));
@@ -669,8 +662,8 @@ pub fn build_target_config(opts: &Options, sp: &SpanHandler) -> Config {
     };
 
     let (int_type, uint_type) = match &target.target_pointer_width[..] {
-        "32" => (hir::TyI32, hir::TyU32),
-        "64" => (hir::TyI64, hir::TyU64),
+        "32" => (ast::TyI32, ast::TyU32),
+        "64" => (ast::TyI64, ast::TyU64),
         w    => sp.handler().fatal(&format!("target specification was invalid: unrecognized \
                                              target-pointer-width {}", w))
     };
@@ -898,38 +891,36 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
     let parse_only = debugging_opts.parse_only;
     let no_trans = debugging_opts.no_trans;
     let treat_err_as_bug = debugging_opts.treat_err_as_bug;
-    let always_build_mir = debugging_opts.always_build_mir;
     let no_analysis = debugging_opts.no_analysis;
 
     if debugging_opts.debug_llvm {
         unsafe { llvm::LLVMSetDebug(1); }
     }
 
-    let mut output_types = Vec::new();
+    let mut output_types = HashMap::new();
     if !debugging_opts.parse_only && !no_trans {
-        let unparsed_output_types = matches.opt_strs("emit");
-        for unparsed_output_type in &unparsed_output_types {
-            for part in unparsed_output_type.split(',') {
-                let output_type = match part {
-                    "asm" => OutputTypeAssembly,
-                    "llvm-ir" => OutputTypeLlvmAssembly,
-                    "llvm-bc" => OutputTypeBitcode,
-                    "obj" => OutputTypeObject,
-                    "link" => OutputTypeExe,
-                    "dep-info" => OutputTypeDepInfo,
-                    _ => {
+        for list in matches.opt_strs("emit") {
+            for output_type in list.split(',') {
+                let mut parts = output_type.splitn(2, '=');
+                let output_type = match parts.next().unwrap() {
+                    "asm" => OutputType::Assembly,
+                    "llvm-ir" => OutputType::LlvmAssembly,
+                    "llvm-bc" => OutputType::Bitcode,
+                    "obj" => OutputType::Object,
+                    "link" => OutputType::Exe,
+                    "dep-info" => OutputType::DepInfo,
+                    part => {
                         early_error(color, &format!("unknown emission type: `{}`",
                                                     part))
                     }
                 };
-                output_types.push(output_type)
+                let path = parts.next().map(PathBuf::from);
+                output_types.insert(output_type, path);
             }
         }
     };
-    output_types.sort();
-    output_types.dedup();
     if output_types.is_empty() {
-        output_types.push(OutputTypeExe);
+        output_types.insert(OutputType::Exe, None);
     }
 
     let cg = build_codegen_options(matches, color);
@@ -1002,7 +993,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
 
     let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
     let test = matches.opt_present("test");
-    let write_dependency_info = (output_types.contains(&OutputTypeDepInfo), None);
 
     let prints = matches.opt_strs("print").into_iter().map(|s| {
         match &*s {
@@ -1054,10 +1044,8 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         parse_only: parse_only,
         no_trans: no_trans,
         treat_err_as_bug: treat_err_as_bug,
-        always_build_mir: always_build_mir,
         no_analysis: no_analysis,
         debugging_opts: debugging_opts,
-        write_dependency_info: write_dependency_info,
         prints: prints,
         cg: cg,
         color: color,
index ff732ee7b9d80c60099da78a70c3c65adec28c11..0a1df25f115a6ef92741ec4d77e91859ea342079 100644 (file)
@@ -15,7 +15,7 @@ use middle::dependency_format;
 use session::search_paths::PathKind;
 use util::nodemap::{NodeMap, FnvHashMap};
 
-use syntax::ast::NodeId;
+use syntax::ast::{NodeId, NodeIdAssigner};
 use syntax::codemap::Span;
 use syntax::diagnostic::{self, Emitter};
 use syntax::diagnostics;
@@ -236,9 +236,6 @@ impl Session {
         }
         lints.insert(id, vec!((lint_id, sp, msg)));
     }
-    pub fn next_node_id(&self) -> ast::NodeId {
-        self.reserve_node_ids(1)
-    }
     pub fn reserve_node_ids(&self, count: ast::NodeId) -> ast::NodeId {
         let id = self.next_node_id.get();
 
@@ -317,6 +314,16 @@ impl Session {
     }
 }
 
+impl NodeIdAssigner for Session {
+    fn next_node_id(&self) -> NodeId {
+        self.reserve_node_ids(1)
+    }
+
+    fn peek_node_id(&self) -> NodeId {
+        self.next_node_id.get().checked_add(1).unwrap()
+    }
+}
+
 fn split_msg_into_multilines(msg: &str) -> Option<String> {
     // Conditions for enabling multi-line errors:
     if !msg.contains("mismatched types") &&
@@ -331,10 +338,10 @@ fn split_msg_into_multilines(msg: &str) -> Option<String> {
     let first = msg.match_indices("expected").filter(|s| {
         s.0 > 0 && (msg.char_at_reverse(s.0) == ' ' ||
                     msg.char_at_reverse(s.0) == '(')
-    }).map(|(a, b)| (a - 1, b));
+    }).map(|(a, b)| (a - 1, a + b.len()));
     let second = msg.match_indices("found").filter(|s| {
         msg.char_at_reverse(s.0) == ' '
-    }).map(|(a, b)| (a - 1, b));
+    }).map(|(a, b)| (a - 1, a + b.len()));
 
     let mut new_msg = String::new();
     let mut head = 0;
index fee60d46dc0019b7436f4986015124092c2e74d8..67ced5d32594d09cfcf6bd26ed3892ce39cc46ac 100644 (file)
@@ -25,9 +25,10 @@ use middle::ty::fold::TypeFoldable;
 
 use std::fmt;
 use syntax::abi;
+use syntax::ast;
 use syntax::parse::token;
-use syntax::ast::DUMMY_NODE_ID;
-use rustc_front::hir as ast;
+use syntax::ast::CRATE_NODE_ID;
+use rustc_front::hir;
 
 pub fn verbose() -> bool {
     ty::tls::with(|tcx| tcx.sess.verbose())
@@ -231,7 +232,7 @@ fn in_binder<'tcx, T, U>(f: &mut fmt::Formatter,
             ty::BrEnv => {
                 let name = token::intern("'r");
                 let _ = write!(f, "{}", name);
-                ty::BrNamed(DefId::local(DUMMY_NODE_ID), name)
+                ty::BrNamed(tcx.map.local_def_id(CRATE_NODE_ID), name)
             }
         })
     }).0;
@@ -308,18 +309,18 @@ impl<'tcx> fmt::Display for ty::TraitTy<'tcx> {
 
 impl<'tcx> fmt::Debug for ty::TypeParameterDef<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "TypeParameterDef({}, {}:{}, {:?}/{})",
+        write!(f, "TypeParameterDef({}, {:?}, {:?}/{})",
                self.name,
-               self.def_id.krate, self.def_id.node,
+               self.def_id,
                self.space, self.index)
     }
 }
 
 impl fmt::Debug for ty::RegionParameterDef {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "RegionParameterDef({}, {}:{}, {:?}/{}, {:?})",
+        write!(f, "RegionParameterDef({}, {:?}, {:?}/{}, {:?})",
                self.name,
-               self.def_id.krate, self.def_id.node,
+               self.def_id,
                self.space, self.index,
                self.bounds)
     }
@@ -334,7 +335,7 @@ impl<'tcx> fmt::Debug for ty::TyS<'tcx> {
 impl<'tcx> fmt::Display for ty::TypeAndMut<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "{}{}",
-               if self.mutbl == ast::MutMutable { "mut " } else { "" },
+               if self.mutbl == hir::MutMutable { "mut " } else { "" },
                self.ty)
     }
 }
@@ -454,7 +455,7 @@ impl fmt::Debug for ty::BoundRegion {
             BrAnon(n) => write!(f, "BrAnon({:?})", n),
             BrFresh(n) => write!(f, "BrFresh({:?})", n),
             BrNamed(did, name) => {
-                write!(f, "BrNamed({}:{}, {:?})", did.krate, did.node, name)
+                write!(f, "BrNamed({:?}, {:?})", did, name)
             }
             BrEnv => "BrEnv".fmt(f),
         }
@@ -465,8 +466,8 @@ impl fmt::Debug for ty::Region {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
             ty::ReEarlyBound(ref data) => {
-                write!(f, "ReEarlyBound({}, {:?}, {}, {})",
-                       data.param_id,
+                write!(f, "ReEarlyBound({:?}, {:?}, {}, {})",
+                       data.def_id,
                        data.space,
                        data.index,
                        data.name)
@@ -825,8 +826,8 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
             TyBox(typ) => write!(f, "Box<{}>",  typ),
             TyRawPtr(ref tm) => {
                 write!(f, "*{} {}", match tm.mutbl {
-                    ast::MutMutable => "mut",
-                    ast::MutImmutable => "const",
+                    hir::MutMutable => "mut",
+                    hir::MutImmutable => "const",
                 },  tm.ty)
             }
             TyRef(r, ref tm) => {
@@ -853,7 +854,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
                 write!(f, ")")
             }
             TyBareFn(opt_def_id, ref bare_fn) => {
-                if bare_fn.unsafety == ast::Unsafety::Unsafe {
+                if bare_fn.unsafety == hir::Unsafety::Unsafe {
                     try!(write!(f, "unsafe "));
                 }
 
@@ -887,15 +888,15 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
             TyTrait(ref data) => write!(f, "{}", data),
             ty::TyProjection(ref data) => write!(f, "{}", data),
             TyStr => write!(f, "str"),
-            TyClosure(ref did, ref substs) => ty::tls::with(|tcx| {
+            TyClosure(did, ref substs) => ty::tls::with(|tcx| {
                 try!(write!(f, "[closure"));
 
-                if did.is_local() {
-                    try!(write!(f, "@{:?}", tcx.map.span(did.node)));
+                if let Some(node_id) = tcx.map.as_local_node_id(did) {
+                    try!(write!(f, "@{:?}", tcx.map.span(node_id)));
                     let mut sep = " ";
-                    try!(tcx.with_freevars(did.node, |freevars| {
+                    try!(tcx.with_freevars(node_id, |freevars| {
                         for (freevar, upvar_ty) in freevars.iter().zip(&substs.upvar_tys) {
-                            let node_id = freevar.def.local_node_id();
+                            let node_id = freevar.def.var_id();
                             try!(write!(f,
                                         "{}{}:{}",
                                         sep,
@@ -966,10 +967,10 @@ impl fmt::Display for ty::ExplicitSelfCategory {
         f.write_str(match *self {
             ty::StaticExplicitSelfCategory => "static",
             ty::ByValueExplicitSelfCategory => "self",
-            ty::ByReferenceExplicitSelfCategory(_, ast::MutMutable) => {
+            ty::ByReferenceExplicitSelfCategory(_, hir::MutMutable) => {
                 "&mut self"
             }
-            ty::ByReferenceExplicitSelfCategory(_, ast::MutImmutable) => "&self",
+            ty::ByReferenceExplicitSelfCategory(_, hir::MutImmutable) => "&self",
             ty::ByBoxExplicitSelfCategory => "Box<self>",
         })
     }
index 4a6646bca1b64f623deda604382a57a472537115..14fb064b7aabe4437cee37ac16eb1bab0643d475 100644 (file)
@@ -33,9 +33,7 @@
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![feature(box_syntax)]
-#![feature(fs_canonicalize)]
 #![feature(libc)]
-#![feature(path_ext)]
 #![feature(rand)]
 #![feature(rustc_private)]
 #![feature(slice_bytes)]
@@ -57,3 +55,4 @@ pub mod rpath;
 pub mod sha2;
 pub mod svh;
 pub mod target;
+pub mod slice;
diff --git a/src/librustc_back/slice.rs b/src/librustc_back/slice.rs
new file mode 100644 (file)
index 0000000..5d8fc3a
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::mem;
+
+pub fn ref_slice<T>(ptr: &T) -> &[T; 1] {
+    unsafe { mem::transmute(ptr) }
+}
+
+pub fn mut_ref_slice<T>(ptr: &mut T) -> &mut [T; 1] {
+    unsafe { mem::transmute(ptr) }
+}
index 5f6bf939fb2a8ec0103e0ec13b202d091ff12f5a..a9cfc7138d8d967808aa44183e7d833035c9b52c 100644 (file)
@@ -131,7 +131,7 @@ mod svh_visitor {
     pub use self::SawExprComponent::*;
     pub use self::SawStmtComponent::*;
     use self::SawAbiComponent::*;
-    use syntax::ast::{self, NodeId, Ident};
+    use syntax::ast::{self, Name, NodeId};
     use syntax::codemap::Span;
     use syntax::parse::token;
     use rustc_front::visit;
@@ -177,7 +177,7 @@ mod svh_visitor {
         SawIdent(token::InternedString),
         SawStructDef(token::InternedString),
 
-        SawLifetimeRef(token::InternedString),
+        SawLifetime(token::InternedString),
         SawLifetimeDef(token::InternedString),
 
         SawMod,
@@ -193,7 +193,6 @@ mod svh_visitor {
         SawVariant,
         SawExplicitSelf,
         SawPath,
-        SawOptLifetimeRef,
         SawBlock,
         SawPat,
         SawLocal,
@@ -232,7 +231,7 @@ mod svh_visitor {
         SawExprTup,
         SawExprBinary(hir::BinOp_),
         SawExprUnary(hir::UnOp),
-        SawExprLit(hir::Lit_),
+        SawExprLit(ast::Lit_),
         SawExprCast,
         SawExprIf,
         SawExprWhile,
@@ -249,7 +248,6 @@ mod svh_visitor {
         SawExprInlineAsm(&'a hir::InlineAsm),
         SawExprStruct,
         SawExprRepeat,
-        SawExprParen,
     }
 
     fn saw_expr<'a>(node: &'a Expr_) -> SawExprComponent<'a> {
@@ -271,7 +269,7 @@ mod svh_visitor {
             ExprBlock(..)            => SawExprBlock,
             ExprAssign(..)           => SawExprAssign,
             ExprAssignOp(op, _, _)   => SawExprAssignOp(op.node),
-            ExprField(_, id)         => SawExprField(id.node.name.as_str()),
+            ExprField(_, name)       => SawExprField(name.node.as_str()),
             ExprTupField(_, id)      => SawExprTupField(id.node),
             ExprIndex(..)            => SawExprIndex,
             ExprRange(..)            => SawExprRange,
@@ -283,7 +281,6 @@ mod svh_visitor {
             ExprInlineAsm(ref asm)   => SawExprInlineAsm(asm),
             ExprStruct(..)           => SawExprStruct,
             ExprRepeat(..)           => SawExprRepeat,
-            ExprParen(..)            => SawExprParen,
         }
     }
 
@@ -304,29 +301,18 @@ mod svh_visitor {
     }
 
     impl<'a, 'v> Visitor<'v> for StrictVersionHashVisitor<'a> {
-        fn visit_struct_def(&mut self, s: &StructDef, ident: Ident,
-                            g: &Generics, _: NodeId) {
-            SawStructDef(ident.name.as_str()).hash(self.st);
+        fn visit_variant_data(&mut self, s: &VariantData, name: Name,
+                            g: &Generics, _: NodeId, _: Span) {
+            SawStructDef(name.as_str()).hash(self.st);
             visit::walk_generics(self, g);
             visit::walk_struct_def(self, s)
         }
 
-        fn visit_variant(&mut self, v: &Variant, g: &Generics) {
+        fn visit_variant(&mut self, v: &Variant, g: &Generics, item_id: NodeId) {
             SawVariant.hash(self.st);
             // walk_variant does not call walk_generics, so do it here.
             visit::walk_generics(self, g);
-            visit::walk_variant(self, v, g)
-        }
-
-        fn visit_opt_lifetime_ref(&mut self, _: Span, l: &Option<Lifetime>) {
-            SawOptLifetimeRef.hash(self.st);
-            // (This is a strange method in the visitor trait, in that
-            // it does not expose a walk function to do the subroutine
-            // calls.)
-            match *l {
-                Some(ref l) => self.visit_lifetime_ref(l),
-                None => ()
-            }
+            visit::walk_variant(self, v, g, item_id)
         }
 
         // All of the remaining methods just record (in the hash
@@ -343,12 +329,12 @@ mod svh_visitor {
         // (If you edit a method such that it deviates from the
         // pattern, please move that method up above this comment.)
 
-        fn visit_ident(&mut self, _: Span, ident: Ident) {
-            SawIdent(ident.name.as_str()).hash(self.st);
+        fn visit_name(&mut self, _: Span, name: Name) {
+            SawIdent(name.as_str()).hash(self.st);
         }
 
-        fn visit_lifetime_ref(&mut self, l: &Lifetime) {
-            SawLifetimeRef(l.name.as_str()).hash(self.st);
+        fn visit_lifetime(&mut self, l: &Lifetime) {
+            SawLifetime(l.name.as_str()).hash(self.st);
         }
 
         fn visit_lifetime_def(&mut self, l: &LifetimeDef) {
@@ -425,6 +411,10 @@ mod svh_visitor {
             SawPath.hash(self.st); visit::walk_path(self, path)
         }
 
+        fn visit_path_list_item(&mut self, prefix: &Path, item: &'v PathListItem) {
+            SawPath.hash(self.st); visit::walk_path_list_item(self, prefix, item)
+        }
+
         fn visit_block(&mut self, b: &Block) {
             SawBlock.hash(self.st); visit::walk_block(self, b)
         }
index e87cb43128d24fc1efffd5d53c16b3673fc91d95..e1242560e62c76b167568aaf797b7a45bd3d6500 100644 (file)
@@ -19,6 +19,7 @@ pub fn target() -> Target {
         arch: "aarch64".to_string(),
         target_os: "ios".to_string(),
         target_env: "".to_string(),
+        target_vendor: "apple".to_string(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+cyclone".to_string(),
             eliminate_frame_pointer: false,
index 8c350e8b28750ef3ec9f04682a257de05b715468..c6901a4cc4270942b16a7a194241732389cac70e 100644 (file)
@@ -18,6 +18,7 @@ pub fn target() -> Target {
         arch: "aarch64".to_string(),
         target_os: "android".to_string(),
         target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
         options: super::android_base::opts(),
     }
 }
index ed79caf486942158402e23ce2d47ce527b923ab8..51abab6609a86c52997e73b576723a21a4204833 100644 (file)
@@ -19,6 +19,7 @@ pub fn target() -> Target {
         target_env: "gnu".to_string(),
         arch: "aarch64".to_string(),
         target_os: "linux".to_string(),
+        target_vendor: "unknown".to_string(),
         options: base,
     }
 }
index 0c4e28d97000834e05c50657fe9817b33cbf82b6..8b75bb3941477b356aef4df75b75e253961f5614 100644 (file)
@@ -24,7 +24,7 @@ pub fn opts() -> TargetOptions {
         dll_suffix: ".dylib".to_string(),
         archive_format: "bsd".to_string(),
         pre_link_args: Vec::new(),
-        exe_allocation_crate: super::best_allocator(),
+        exe_allocation_crate: super::maybe_jemalloc(),
         .. Default::default()
     }
 }
index 0770fe70e8a5780b69c6e28739fca356d9def1fa..732f1a353a8bd719c1f363e5fec3c02c9837765d 100644 (file)
@@ -21,6 +21,7 @@ pub fn target() -> Target {
         arch: "arm".to_string(),
         target_os: "android".to_string(),
         target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
         options: base,
     }
 }
index 084f989277f317024220d1290a180deda2339d2d..7c35b43fd4b7544ea442bbed0273daffb491af97 100644 (file)
@@ -19,6 +19,7 @@ pub fn target() -> Target {
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnueabi".to_string(),
+        target_vendor: "unknown".to_string(),
 
         options: TargetOptions {
             features: "+v6".to_string(),
index 08f1aa5ade848c6c9d6503c44d463b3b61f0a9db..a99ec45996c2e833c2b14505f4471581aa7b2532 100644 (file)
@@ -19,6 +19,7 @@ pub fn target() -> Target {
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnueabihf".to_string(),
+        target_vendor: "unknown".to_string(),
 
         options: TargetOptions {
             features: "+v6,+vfp2".to_string(),
index a6d649ea162f93be4cab857075cf4af188055781..d30648002912e6831cf8bd4ff36f7e8bc33e8b95 100644 (file)
@@ -19,6 +19,7 @@ pub fn target() -> Target {
         arch: "arm".to_string(),
         target_os: "ios".to_string(),
         target_env: "".to_string(),
+        target_vendor: "apple".to_string(),
         options: TargetOptions {
             features: "+v7,+vfp3,+neon".to_string(),
             .. opts(Arch::Armv7)
index 264385512added148a0519249939a5bcfee2711e..66ec6efca0e6700a925f60a830b0631eab6cb549 100644 (file)
@@ -19,6 +19,7 @@ pub fn target() -> Target {
         arch: "arm".to_string(),
         target_os: "ios".to_string(),
         target_env: "".to_string(),
+        target_vendor: "apple".to_string(),
         options: TargetOptions {
             features: "+v7,+vfp4,+neon".to_string(),
             .. opts(Arch::Armv7s)
index 96680dc37596551dfa273331ac7f0303e398fa3c..2b84244cda4a2ef2f903bd532867e770a2fc9d4c 100644 (file)
@@ -20,7 +20,7 @@ pub fn opts() -> TargetOptions {
         has_rpath: true,
         position_independent_executables: true,
         archive_format: "gnu".to_string(),
-        exe_allocation_crate: super::best_allocator(),
+        exe_allocation_crate: "alloc_system".to_string(),
 
         .. Default::default()
     }
index 41c5f36099e8012a3cf99824d11e937cc3a118bf..b78fdc9f59ba1103063cb2863e1ab87efaf5fa80 100644 (file)
@@ -27,7 +27,7 @@ pub fn opts() -> TargetOptions {
         ),
         position_independent_executables: true,
         archive_format: "gnu".to_string(),
-        exe_allocation_crate: super::best_allocator(),
+        exe_allocation_crate: super::maybe_jemalloc(),
         .. Default::default()
     }
 }
index a5807d2787fdd726ebf4b5fda601c93696e614a9..e955f8c302bd64977a0b8c84e0d17c49bd153963 100644 (file)
@@ -18,7 +18,7 @@ pub fn opts() -> TargetOptions {
         executables: true,
         has_rpath: true,
         archive_format: "gnu".to_string(),
-        exe_allocation_crate: super::best_allocator(),
+        exe_allocation_crate: super::maybe_jemalloc(),
 
         .. Default::default()
     }
index d17aa915461df369a192a5bf13c88f303cea204a..52b5901192c657ae436d6bd9d46a2d86c1b9645d 100644 (file)
@@ -19,6 +19,7 @@ pub fn target() -> Target {
         arch: "x86".to_string(),
         target_os: "ios".to_string(),
         target_env: "".to_string(),
+        target_vendor: "apple".to_string(),
         options: opts(Arch::I386)
     }
 }
index 9fe15e76942863c7ada3bf69aa878905f8e3ccb2..98f4654ecab41ab9390d71e2443ed6b8dcf2e6c7 100644 (file)
@@ -22,6 +22,7 @@ pub fn target() -> Target {
         arch: "x86".to_string(),
         target_os: "macos".to_string(),
         target_env: "".to_string(),
+        target_vendor: "apple".to_string(),
         options: base,
     }
 }
index 708e7756b94bdda2b385b719f1ccf2f8068b3aa0..f548fdad3cbed9d81fd6f6a76007ea3d838ccccb 100644 (file)
@@ -21,6 +21,7 @@ pub fn target() -> Target {
         arch: "x86".to_string(),
         target_os: "android".to_string(),
         target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
         options: base,
     }
 }
index ae1b4d450a58e93792f636f42e9ac966720a0308..c825f6043d27b3adf4fa7c40088eb283ec7acb3e 100644 (file)
@@ -30,6 +30,7 @@ pub fn target() -> Target {
         arch: "x86".to_string(),
         target_os: "windows".to_string(),
         target_env: "gnu".to_string(),
+        target_vendor: "pc".to_string(),
         options: options,
     }
 }
index d8c1c79b47fcd9ce727ac1b4be3aed94101631e2..96b2d37ab2088135a374386130487e12905b1533 100644 (file)
@@ -21,6 +21,7 @@ pub fn target() -> Target {
         arch: "x86".to_string(),
         target_os: "windows".to_string(),
         target_env: "msvc".to_string(),
+        target_vendor: "pc".to_string(),
         options: base,
     }
 }
index f2478e6d0dbfeb37cfe8765013a60a5aafc2d2c7..32a15b9f2d4d10c0ce3ab290a98ce1543197f17f 100644 (file)
@@ -22,6 +22,7 @@ pub fn target() -> Target {
         arch: "x86".to_string(),
         target_os: "dragonfly".to_string(),
         target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
         options: base,
     }
 }
index 6b2d9b5053c4ae6ebff10b62b0ecbd16981ef790..812ba11cd796b3ae39a7c8511c7f64f1aaaef2fc 100644 (file)
@@ -22,6 +22,7 @@ pub fn target() -> Target {
         arch: "x86".to_string(),
         target_os: "freebsd".to_string(),
         target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
         options: base,
     }
 }
index 074d5b2b9ed228d5be4995a2f78c5e0d55b77b18..ac2af0c64fd6ad2b1239860af8803b38f277022c 100644 (file)
@@ -22,6 +22,7 @@ pub fn target() -> Target {
         arch: "x86".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
         options: base,
     }
 }
diff --git a/src/librustc_back/target/le32_unknown_nacl.rs b/src/librustc_back/target/le32_unknown_nacl.rs
new file mode 100644 (file)
index 0000000..a5daeba
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::{Target, TargetOptions};
+
+pub fn target() -> Target {
+    let opts = TargetOptions {
+        linker: "pnacl-clang".to_string(),
+        ar: "pnacl-ar".to_string(),
+
+        pre_link_args: vec!("--pnacl-exceptions=sjlj".to_string(),
+                            "--target=le32-unknown-nacl".to_string(),
+                            "-Wl,--start-group".to_string()),
+        post_link_args: vec!("-Wl,--end-group".to_string()),
+        dynamic_linking: false,
+        executables: true,
+        exe_suffix: ".pexe".to_string(),
+        no_compiler_rt: false,
+        linker_is_gnu: true,
+        allow_asm: false,
+        archive_format: "gnu".to_string(),
+        .. Default::default()
+    };
+    Target {
+        llvm_target: "le32-unknown-nacl".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_os: "nacl".to_string(),
+        target_env: "newlib".to_string(),
+        target_vendor: "unknown".to_string(),
+        arch: "le32".to_string(),
+        options: opts,
+    }
+}
index d6b50a955b6829ddc6d54dc14c548dd4d72946dd..6492fa5015970e07ca149a11c3ab32866dadf997 100644 (file)
@@ -29,7 +29,7 @@ pub fn opts() -> TargetOptions {
         ],
         position_independent_executables: true,
         archive_format: "gnu".to_string(),
-        exe_allocation_crate: super::best_allocator(),
+        exe_allocation_crate: super::maybe_jemalloc(),
         .. Default::default()
     }
 }
index 3f3da6d6c9136aa86448c17ead7d1d761b37b021..357499c48ec7a5d9ae56c7b698b99aee5b4b3086 100644 (file)
@@ -18,6 +18,7 @@ pub fn target() -> Target {
         arch: "mips".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
         options: super::linux_base::opts()
     }
 }
index d7f286c8aa4085beda3357ee7c6cbb9b062a2785..3d0088add0d537d5d6703a7f920206e493bedf66 100644 (file)
@@ -18,6 +18,7 @@ pub fn target() -> Target {
         arch: "mips".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
 
         options: super::linux_base::opts()
     }
index 56562c8dfdbf6a1cecded75bf90466b5f85ea701..6ae74355a7a8a6db989840c2466043dee9b74577 100644 (file)
@@ -77,6 +77,8 @@ pub struct Target {
     pub target_os: String,
     /// Environment name to use for conditional compilation.
     pub target_env: String,
+    /// Vendor name to use for conditional compilation.
+    pub target_vendor: String,
     /// Architecture to use for ABI considerations. Valid options: "x86", "x86_64", "arm",
     /// "aarch64", "mips", and "powerpc". "mips" includes "mipsel".
     pub arch: String,
@@ -157,6 +159,9 @@ pub struct TargetOptions {
     /// Whether to disable linking to compiler-rt. Defaults to false, as LLVM
     /// will emit references to the functions that compiler-rt provides.
     pub no_compiler_rt: bool,
+    /// Whether to disable linking to the default libraries, typically corresponds
+    /// to `-nodefaultlibs`. Defaults to true.
+    pub no_default_libraries: bool,
     /// Dynamically linked executables can be compiled as position independent
     /// if the default relocation model of position independent code is not
     /// changed. This is a requirement to take advantage of ASLR, as otherwise
@@ -212,6 +217,7 @@ impl Default for TargetOptions {
             linker_is_gnu: false,
             has_rpath: false,
             no_compiler_rt: false,
+            no_default_libraries: true,
             position_independent_executables: false,
             pre_link_objects: Vec::new(),
             post_link_objects: Vec::new(),
@@ -256,14 +262,20 @@ impl Target {
             }
         };
 
+        let get_opt_field = |name: &str, default: &str| {
+            obj.find(name).and_then(|s| s.as_string())
+               .map(|s| s.to_string())
+               .unwrap_or(default.to_string())
+        };
+
         let mut base = Target {
             llvm_target: get_req_field("llvm-target"),
             target_endian: get_req_field("target-endian"),
             target_pointer_width: get_req_field("target-pointer-width"),
             arch: get_req_field("arch"),
             target_os: get_req_field("os"),
-            target_env: obj.find("env").and_then(|s| s.as_string())
-                           .map(|s| s.to_string()).unwrap_or(String::new()),
+            target_env: get_opt_field("env", ""),
+            target_vendor: get_opt_field("vendor", "unknown"),
             options: Default::default(),
         };
 
@@ -319,6 +331,7 @@ impl Target {
         key!(linker_is_gnu, bool);
         key!(has_rpath, bool);
         key!(no_compiler_rt, bool);
+        key!(no_default_libraries, bool);
         key!(pre_link_args, list);
         key!(post_link_args, list);
         key!(allow_asm, bool);
@@ -398,6 +411,7 @@ impl Target {
             x86_64_unknown_bitrig,
             x86_64_unknown_openbsd,
             x86_64_unknown_netbsd,
+            x86_64_rumprun_netbsd,
 
             x86_64_apple_darwin,
             i686_apple_darwin,
@@ -412,7 +426,9 @@ impl Target {
             i686_pc_windows_gnu,
 
             x86_64_pc_windows_msvc,
-            i686_pc_windows_msvc
+            i686_pc_windows_msvc,
+
+            le32_unknown_nacl
         );
 
 
@@ -444,7 +460,7 @@ impl Target {
     }
 }
 
-fn best_allocator() -> String {
+fn maybe_jemalloc() -> String {
     if cfg!(disable_jemalloc) {
         "alloc_system".to_string()
     } else {
index 3b02111d93444fbd4cdf34e739890494438da72e..2e4aa27cf889d22659b909e2221c5e5e6d9d8182 100644 (file)
@@ -27,7 +27,7 @@ pub fn opts() -> TargetOptions {
         ),
         position_independent_executables: true,
         archive_format: "gnu".to_string(),
-        exe_allocation_crate: super::best_allocator(),
+        exe_allocation_crate: "alloc_system".to_string(),
         .. Default::default()
     }
 }
index 896824eba0e56b627bbb4ce14ae0caf6f745d11d..6664abf5458b715253ba2177079de42e9bcd6358 100644 (file)
@@ -21,6 +21,7 @@ pub fn target() -> Target {
         arch: "powerpc".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
         options: base,
     }
 }
index fedae51e0e894cfe46af30a26b271c34658895d1..2e5973679022d7c05a56544db0e9cd84ff2c6fc9 100644 (file)
@@ -23,6 +23,10 @@ pub fn opts() -> TargetOptions {
         exe_suffix: ".exe".to_string(),
         staticlib_prefix: "".to_string(),
         staticlib_suffix: ".lib".to_string(),
+        // Unfortunately right now passing -nodefaultlibs to gcc on windows
+        // doesn't work so hot (in terms of native dependencies). This flag
+        // should hopefully be removed one day though!
+        no_default_libraries: false,
         is_like_windows: true,
         archive_format: "gnu".to_string(),
         pre_link_args: vec!(
@@ -60,7 +64,7 @@ pub fn opts() -> TargetOptions {
             // Always enable DEP (NX bit) when it is available
             "-Wl,--nxcompat".to_string(),
         ),
-        exe_allocation_crate: super::best_allocator(),
+        exe_allocation_crate: super::maybe_jemalloc(),
 
         .. Default::default()
     }
index fe9ac32ee8fb5251483ef3f8a55d1f98ec2455aa..fb88ce158e4b3db5e0f25d217101df06ac247dec 100644 (file)
@@ -60,7 +60,7 @@ pub fn opts() -> TargetOptions {
             "/NXCOMPAT".to_string(),
         ],
         archive_format: "gnu".to_string(),
-        exe_allocation_crate: super::best_allocator(),
+        exe_allocation_crate: "alloc_system".to_string(),
 
         .. Default::default()
     }
index ef40c2f2006e1628086bdb2906f30d6748b6118b..3e19e1482909e2b85e317755c2b5f5e70e71f2f5 100644 (file)
@@ -23,6 +23,7 @@ pub fn target() -> Target {
         arch: "x86_64".to_string(),
         target_os: "macos".to_string(),
         target_env: "".to_string(),
+        target_vendor: "apple".to_string(),
         options: base,
     }
 }
index 7aca8c554dab63dd27c6d9b980dc1a1f3b464ceb..63234c0baee8cf14055b360dee9a57b81d1e0afb 100644 (file)
@@ -19,6 +19,7 @@ pub fn target() -> Target {
         arch: "x86_64".to_string(),
         target_os: "ios".to_string(),
         target_env: "".to_string(),
+        target_vendor: "apple".to_string(),
         options: opts(Arch::X86_64)
     }
 }
index aef1d7471b85b1d415f2d723dcb66bf11b2d2bf0..2bd363e46bb1cf7c711880ced70b8e8b44c514e2 100644 (file)
@@ -25,6 +25,7 @@ pub fn target() -> Target {
         arch: "x86_64".to_string(),
         target_os: "windows".to_string(),
         target_env: "gnu".to_string(),
+        target_vendor: "pc".to_string(),
         options: base,
     }
 }
index 85756db96061fc81f8b1fa227f33ab37e207c863..5030a1ff4483baaf84ccbb7c6b8af9c0ab8f505f 100644 (file)
@@ -22,6 +22,7 @@ pub fn target() -> Target {
         arch: "x86_64".to_string(),
         target_os: "windows".to_string(),
         target_env: "msvc".to_string(),
+        target_vendor: "pc".to_string(),
         options: base,
     }
 }
diff --git a/src/librustc_back/target/x86_64_rumprun_netbsd.rs b/src/librustc_back/target/x86_64_rumprun_netbsd.rs
new file mode 100644 (file)
index 0000000..d63ad53
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::Target;
+
+pub fn target() -> Target {
+    let mut base = super::netbsd_base::opts();
+    base.pre_link_args.push("-m64".to_string());
+    base.linker = "x86_64-rumprun-netbsd-gcc".to_string();
+    base.ar = "x86_64-rumprun-netbsd-ar".to_string();
+
+    base.dynamic_linking = false;
+    base.has_rpath = false;
+    base.position_independent_executables = false;
+    base.disable_redzone = true;
+    base.no_default_libraries = false;
+
+    Target {
+        llvm_target: "x86_64-rumprun-netbsd".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        arch: "x86_64".to_string(),
+        target_os: "netbsd".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "rumprun".to_string(),
+        options: base,
+    }
+}
index 6ecf885aba38eff9cf1f1e9441001c32ccf3a3ca..04456b1b2714a495a786a7d3ac3270425cad6e7a 100644 (file)
@@ -21,6 +21,7 @@ pub fn target() -> Target {
         arch: "x86_64".to_string(),
         target_os: "bitrig".to_string(),
         target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
         options: base,
     }
 }
index f0e665967ec6f3fd2b77304ce1ec28f584b79543..62654176aa486738201c7b3b7fab3d0e62307d87 100644 (file)
@@ -22,6 +22,7 @@ pub fn target() -> Target {
         arch: "x86_64".to_string(),
         target_os: "dragonfly".to_string(),
         target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
         options: base,
     }
 }
index f742ebfde1d2c314fdf2e28e54c72d38e76f8613..888b7f58bffca9264418b961cfb6dcd5d56ab1c0 100644 (file)
@@ -22,6 +22,7 @@ pub fn target() -> Target {
         arch: "x86_64".to_string(),
         target_os: "freebsd".to_string(),
         target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
         options: base,
     }
 }
index 4749e481fd85534724ff1bba722cd73ffc9e557f..e3ccd9c4c7e7dd8ae7c9e68e316b64c3de6bdee9 100644 (file)
@@ -22,6 +22,7 @@ pub fn target() -> Target {
         arch: "x86_64".to_string(),
         target_os: "linux".to_string(),
         target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
         options: base,
     }
 }
index c66192c28b13d7ce1ef2ddddd1f03dd891ba679c..a5ac78cd5b6081850a008bb98acbd5dd5cb4ad0b 100644 (file)
@@ -76,6 +76,7 @@ pub fn target() -> Target {
         arch: "x86_64".to_string(),
         target_os: "linux".to_string(),
         target_env: "musl".to_string(),
+        target_vendor: "unknown".to_string(),
         options: base,
     }
 }
index e13e58e3a186d163d22cc7a3dfc3c0491dad20c9..4101fabe73480eb518ed67387a298a7592105a5e 100644 (file)
@@ -21,6 +21,7 @@ pub fn target() -> Target {
         arch: "x86_64".to_string(),
         target_os: "netbsd".to_string(),
         target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
         options: base,
     }
 }
index a404db48b22bb38875769d86e8d82b675e46ccf8..07a1e137b4196b798c8fd50dd16ced5a3529e460 100644 (file)
@@ -21,6 +21,7 @@ pub fn target() -> Target {
         arch: "x86_64".to_string(),
         target_os: "openbsd".to_string(),
         target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
         options: base,
     }
 }
index 3ee45c3506e1907a1fe355efbd437787764ab9fc..16f586cf5e0627487883b2f37b90496635b1520f 100644 (file)
@@ -22,7 +22,9 @@
 
 //! A typesafe bitmask flag generator.
 
-#[cfg(test)] #[macro_use] extern crate std;
+#[cfg(test)]
+#[macro_use]
+extern crate std;
 
 /// The `bitflags!` macro generates a `struct` that holds a set of C-style
 /// bitmask flags. It is useful for creating typesafe wrappers for C APIs.
@@ -321,7 +323,7 @@ mod tests {
     }
 
     #[test]
-    fn test_bits(){
+    fn test_bits() {
         assert_eq!(Flags::empty().bits(), 0b00000000);
         assert_eq!(Flags::FlagA.bits(), 0b00000001);
         assert_eq!(Flags::FlagABC.bits(), 0b00000111);
@@ -354,7 +356,7 @@ mod tests {
     }
 
     #[test]
-    fn test_is_empty(){
+    fn test_is_empty() {
         assert!(Flags::empty().is_empty());
         assert!(!Flags::FlagA.is_empty());
         assert!(!Flags::FlagABC.is_empty());
@@ -413,7 +415,7 @@ mod tests {
     }
 
     #[test]
-    fn test_insert(){
+    fn test_insert() {
         let mut e1 = Flags::FlagA;
         let e2 = Flags::FlagA | Flags::FlagB;
         e1.insert(e2);
@@ -425,7 +427,7 @@ mod tests {
     }
 
     #[test]
-    fn test_remove(){
+    fn test_remove() {
         let mut e1 = Flags::FlagA | Flags::FlagB;
         let e2 = Flags::FlagA | Flags::FlagC;
         e1.remove(e2);
@@ -484,12 +486,12 @@ mod tests {
 
     #[test]
     fn test_hash() {
-      let mut x = Flags::empty();
-      let mut y = Flags::empty();
-      assert!(hash(&x) == hash(&y));
-      x = Flags::all();
-      y = Flags::FlagABC;
-      assert!(hash(&x) == hash(&y));
+        let mut x = Flags::empty();
+        let mut y = Flags::empty();
+        assert!(hash(&x) == hash(&y));
+        x = Flags::all();
+        y = Flags::FlagABC;
+        assert!(hash(&x) == hash(&y));
     }
 
     fn hash<T: Hash>(t: &T) -> u64 {
index eed8f82b5d853f1a3c13604df0d17c5c85123b00..ff5d364b968e578c92fa5f8ad1a8f13e5b7e1d0e 100644 (file)
@@ -363,13 +363,14 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
         let new_loan_indices = self.loans_generated_by(node);
         debug!("new_loan_indices = {:?}", new_loan_indices);
 
-        self.each_issued_loan(node, |issued_loan| {
-            for &new_loan_index in &new_loan_indices {
+        for &new_loan_index in &new_loan_indices {
+            self.each_issued_loan(node, |issued_loan| {
                 let new_loan = &self.all_loans[new_loan_index];
-                self.report_error_if_loans_conflict(issued_loan, new_loan);
-            }
-            true
-        });
+                // Only report an error for the first issued loan that conflicts
+                // to avoid O(n^2) errors.
+                self.report_error_if_loans_conflict(issued_loan, new_loan)
+            });
+        }
 
         for (i, &x) in new_loan_indices.iter().enumerate() {
             let old_loan = &self.all_loans[x];
@@ -382,7 +383,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
 
     pub fn report_error_if_loans_conflict(&self,
                                           old_loan: &Loan<'tcx>,
-                                          new_loan: &Loan<'tcx>) {
+                                          new_loan: &Loan<'tcx>)
+                                          -> bool {
         //! Checks whether `old_loan` and `new_loan` can safely be issued
         //! simultaneously.
 
@@ -397,7 +399,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
         self.report_error_if_loan_conflicts_with_restriction(
             old_loan, new_loan, old_loan, new_loan) &&
         self.report_error_if_loan_conflicts_with_restriction(
-            new_loan, old_loan, old_loan, new_loan);
+            new_loan, old_loan, old_loan, new_loan)
     }
 
     pub fn report_error_if_loan_conflicts_with_restriction(&self,
@@ -464,40 +466,36 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
 
             match (new_loan.kind, old_loan.kind) {
                 (ty::MutBorrow, ty::MutBorrow) => {
-                    self.bccx.span_err(
-                        new_loan.span,
-                        &format!("cannot borrow `{}`{} as mutable \
-                                more than once at a time",
-                                nl, new_loan_msg))
+                    span_err!(self.bccx, new_loan.span, E0499,
+                              "cannot borrow `{}`{} as mutable \
+                               more than once at a time",
+                              nl, new_loan_msg);
                 }
 
                 (ty::UniqueImmBorrow, _) => {
-                    self.bccx.span_err(
-                        new_loan.span,
-                        &format!("closure requires unique access to `{}` \
-                                but {} is already borrowed{}",
-                                nl, ol_pronoun, old_loan_msg));
+                    span_err!(self.bccx, new_loan.span, E0500,
+                              "closure requires unique access to `{}` \
+                               but {} is already borrowed{}",
+                              nl, ol_pronoun, old_loan_msg);
                 }
 
                 (_, ty::UniqueImmBorrow) => {
-                    self.bccx.span_err(
-                        new_loan.span,
-                        &format!("cannot borrow `{}`{} as {} because \
-                                previous closure requires unique access",
-                                nl, new_loan_msg, new_loan.kind.to_user_str()));
+                    span_err!(self.bccx, new_loan.span, E0501,
+                              "cannot borrow `{}`{} as {} because \
+                               previous closure requires unique access",
+                              nl, new_loan_msg, new_loan.kind.to_user_str());
                 }
 
                 (_, _) => {
-                    self.bccx.span_err(
-                        new_loan.span,
-                        &format!("cannot borrow `{}`{} as {} because \
-                                {} is also borrowed as {}{}",
-                                nl,
-                                new_loan_msg,
-                                new_loan.kind.to_user_str(),
-                                ol_pronoun,
-                                old_loan.kind.to_user_str(),
-                                old_loan_msg));
+                    span_err!(self.bccx, new_loan.span, E0502,
+                              "cannot borrow `{}`{} as {} because \
+                               {} is also borrowed as {}{}",
+                              nl,
+                              new_loan_msg,
+                              new_loan.kind.to_user_str(),
+                              ol_pronoun,
+                              old_loan.kind.to_user_str(),
+                              old_loan_msg);
                 }
             }
 
@@ -617,11 +615,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
         match self.analyze_restrictions_on_use(id, copy_path, ty::ImmBorrow) {
             UseOk => { }
             UseWhileBorrowed(loan_path, loan_span) => {
-                self.bccx.span_err(
-                    span,
-                    &format!("cannot use `{}` because it was mutably borrowed",
-                            &self.bccx.loan_path_to_string(copy_path))
-                    );
+                span_err!(self.bccx, span, E0503,
+                          "cannot use `{}` because it was mutably borrowed",
+                          &self.bccx.loan_path_to_string(copy_path));
                 self.bccx.span_note(
                     loan_span,
                     &format!("borrow of `{}` occurs here",
@@ -642,18 +638,19 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
         match self.analyze_restrictions_on_use(id, move_path, ty::MutBorrow) {
             UseOk => { }
             UseWhileBorrowed(loan_path, loan_span) => {
-                let err_message = match move_kind {
+                match move_kind {
                     move_data::Captured =>
-                        format!("cannot move `{}` into closure because it is borrowed",
-                                &self.bccx.loan_path_to_string(move_path)),
+                        span_err!(self.bccx, span, E0504,
+                                  "cannot move `{}` into closure because it is borrowed",
+                                  &self.bccx.loan_path_to_string(move_path)),
                     move_data::Declared |
                     move_data::MoveExpr |
                     move_data::MovePat =>
-                        format!("cannot move out of `{}` because it is borrowed",
-                                &self.bccx.loan_path_to_string(move_path))
+                        span_err!(self.bccx, span, E0505,
+                                  "cannot move out of `{}` because it is borrowed",
+                                  &self.bccx.loan_path_to_string(move_path))
                 };
 
-                self.bccx.span_err(span, &err_message[..]);
                 self.bccx.span_note(
                     loan_span,
                     &format!("borrow of `{}` occurs here",
@@ -820,10 +817,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
                                    span: Span,
                                    loan_path: &LoanPath<'tcx>,
                                    loan: &Loan) {
-        self.bccx.span_err(
-            span,
-            &format!("cannot assign to `{}` because it is borrowed",
-                    self.bccx.loan_path_to_string(loan_path)));
+        span_err!(self.bccx, span, E0506,
+                  "cannot assign to `{}` because it is borrowed",
+                  self.bccx.loan_path_to_string(loan_path));
         self.bccx.span_note(
             loan.span,
             &format!("borrow of `{}` occurs here",
index 86b6314b57cc114da522b3995b6dcdf629321aeb..1639fcf77a66122120d7abaac5747e8bc1f6419f 100644 (file)
@@ -20,7 +20,7 @@ use borrowck::LoanPathKind::{LpVar, LpUpvar, LpDowncast, LpExtend};
 use borrowck::LoanPathElem::{LpDeref, LpInterior};
 use borrowck::move_data::InvalidMovePathIndex;
 use borrowck::move_data::{MoveData, MovePathIndex};
-use rustc::middle::def_id::{DefId, LOCAL_CRATE};
+use rustc::middle::def_id::{DefId};
 use rustc::middle::ty;
 use rustc::middle::mem_categorization as mc;
 
@@ -28,7 +28,7 @@ use std::mem;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::codemap::Span;
-use rustc_front::attr::AttrMetaMethods;
+use syntax::attr::AttrMetaMethods;
 
 #[derive(PartialEq, Eq, PartialOrd, Ord)]
 enum Fragment {
@@ -133,7 +133,7 @@ pub fn build_unfragmented_map(this: &mut borrowck::BorrowckCtxt,
     }
 
     let mut fraginfo_map = this.tcx.fragment_infos.borrow_mut();
-    let fn_did = DefId { krate: LOCAL_CRATE, node: id };
+    let fn_did = this.tcx.map.local_def_id(id);
     let prev = fraginfo_map.insert(fn_did, fragment_infos);
     assert!(prev.is_none());
 }
@@ -159,7 +159,7 @@ pub struct FragmentSets {
     /// FIXME(pnkfelix) probably do not want/need
     /// `parents_of_fragments` at all, if we can avoid it.
     ///
-    /// Update: I do not see a way to to avoid it.  Maybe just remove
+    /// Update: I do not see a way to avoid it.  Maybe just remove
     /// above fixme, or at least document why doing this may be hard.
     parents_of_fragments: Vec<MovePathIndex>,
 
index 3515b53b00d31f6a1928f496c3c707b101a1afdd..83fac73b7f9dfd86b2232a7dd75fa457c59f13a7 100644 (file)
@@ -99,7 +99,7 @@ pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     let pat_span_path_opt = match move_pat.node {
         hir::PatIdent(_, ref path1, _) => {
             Some(MoveSpanAndPath{span: move_pat.span,
-                                 ident: path1.node})
+                                 name: path1.node.name})
         },
         _ => None,
     };
index c39b1a9da07ea9547858d2a9047cbeed5f2c8c95..59f914895ae59e34183a7a7622ccfe4a792d2a51 100644 (file)
@@ -15,7 +15,6 @@ use rustc::middle::ty;
 use std::cell::RefCell;
 use syntax::ast;
 use syntax::codemap;
-use rustc_front::print::pprust;
 use rustc_front::hir;
 
 pub struct MoveErrorCollector<'tcx> {
@@ -57,7 +56,7 @@ impl<'tcx> MoveError<'tcx> {
 #[derive(Clone)]
 pub struct MoveSpanAndPath {
     pub span: codemap::Span,
-    pub ident: ast::Ident
+    pub name: ast::Name,
 }
 
 pub struct GroupedMoveErrors<'tcx> {
@@ -73,7 +72,7 @@ fn report_move_errors<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         let mut is_first_note = true;
         for move_to in &error.move_to_places {
             note_move_destination(bccx, move_to.span,
-                                  &move_to.ident, is_first_note);
+                                  move_to.name, is_first_note);
             is_first_note = false;
         }
     }
@@ -119,18 +118,18 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         mc::cat_deref(_, _, mc::Implicit(..)) |
         mc::cat_deref(_, _, mc::UnsafePtr(..)) |
         mc::cat_static_item => {
-            bccx.span_err(move_from.span,
-                          &format!("cannot move out of {}",
-                                  move_from.descriptive_string(bccx.tcx)));
+            span_err!(bccx, move_from.span, E0507,
+                      "cannot move out of {}",
+                      move_from.descriptive_string(bccx.tcx));
         }
 
         mc::cat_interior(ref b, mc::InteriorElement(Kind::Index, _)) => {
             let expr = bccx.tcx.map.expect_expr(move_from.id);
             if let hir::ExprIndex(..) = expr.node {
-                bccx.span_err(move_from.span,
-                              &format!("cannot move out of type `{}`, \
-                                        a non-copy fixed-size array",
-                                       b.ty));
+                span_err!(bccx, move_from.span, E0508,
+                          "cannot move out of type `{}`, \
+                           a non-copy fixed-size array",
+                          b.ty);
             }
         }
 
@@ -139,11 +138,10 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
             match b.ty.sty {
                 ty::TyStruct(def, _) |
                 ty::TyEnum(def, _) if def.has_dtor() => {
-                    bccx.span_err(
-                        move_from.span,
-                        &format!("cannot move out of type `{}`, \
-                                 which defines the `Drop` trait",
-                                b.ty));
+                    span_err!(bccx, move_from.span, E0509,
+                              "cannot move out of type `{}`, \
+                               which defines the `Drop` trait",
+                              b.ty);
                 },
                 _ => {
                     bccx.span_bug(move_from.span, "this path should not cause illegal move")
@@ -158,9 +156,8 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
 
 fn note_move_destination(bccx: &BorrowckCtxt,
                          move_to_span: codemap::Span,
-                         pat_ident: &ast::Ident,
+                         pat_name: ast::Name,
                          is_first_note: bool) {
-    let pat_name = pprust::ident_to_string(pat_ident);
     if is_first_note {
         bccx.span_note(
             move_to_span,
index 57e578d10c668d073bfc6bae350d27ad665f76a0..10e29ef843cd3e65ace904e27f0a004f447e7955 100644 (file)
@@ -373,7 +373,7 @@ const DOWNCAST_PRINTED_OPERATOR: &'static str = " as ";
 
 // A local, "cleaned" version of `mc::InteriorKind` that drops
 // information that is not relevant to loan-path analysis. (In
-// particular, the distinction between how precisely a array-element
+// particular, the distinction between how precisely an array-element
 // is tracked is irrelevant here.)
 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub enum InteriorKind {
@@ -803,6 +803,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
         self.tcx.sess.span_err(s, m);
     }
 
+    pub fn span_err_with_code(&self, s: Span, msg: &str, code: &str) {
+        self.tcx.sess.span_err_with_code(s, msg, code);
+    }
+
     pub fn span_bug(&self, s: Span, m: &str) {
         self.tcx.sess.span_bug(s, m);
     }
index e94a214309d1ef2cb422516ebccdc78cf62d1ec3..a5b313e2dd67ee90098f893ae341c0939c7c85be 100644 (file)
@@ -263,12 +263,50 @@ fn mutable() {
 You can read more about cell types in the API documentation:
 
 https://doc.rust-lang.org/std/cell/
-"##
+"##,
+
+E0499: r##"
+A variable was borrowed as mutable more than once. Erroneous code example:
+
+```
+let mut i = 0;
+let mut x = &mut i;
+let mut a = &mut i;
+// error: cannot borrow `i` as mutable more than once at a time
+```
+
+Please note that in rust, you can either have many immutable references, or one
+mutable reference. Take a look at
+https://doc.rust-lang.org/stable/book/references-and-borrowing.html for more
+information. Example:
+
+
+```
+let mut i = 0;
+let mut x = &mut i; // ok!
+
+// or:
+let mut i = 0;
+let a = &i; // ok!
+let b = &i; // still ok!
+let c = &i; // still ok!
+```
+"##,
 
 }
 
 register_diagnostics! {
     E0385, // {} in an aliasable location
     E0388, // {} in a static location
-    E0389  // {} in a `&` reference
+    E0389, // {} in a `&` reference
+    E0500, // closure requires unique access to `..` but .. is already borrowed
+    E0501, // cannot borrow `..`.. as .. because previous closure requires unique access
+    E0502, // cannot borrow `..`.. as .. because .. is also borrowed as ...
+    E0503, // cannot use `..` because it was mutably borrowed
+    E0504, // cannot move `..` into closure because it is borrowed
+    E0505, // cannot move out of `..` because it is borrowed
+    E0506, // cannot assign to `..` because it is borrowed
+    E0507, // cannot move out of ..
+    E0508, // cannot move out of type `..`, a non-copy fixed-size array
+    E0509, // cannot move out of type `..`, which defines the `Drop` trait
 }
index f3038624ac107e467a5304d4569e550f6d2e3975..c9e4d30fef6416568d11237f298e5555e4d1bffb 100644 (file)
@@ -12,7 +12,7 @@ use rustc::front;
 use rustc::front::map as hir_map;
 use rustc_mir as mir;
 use rustc::session::Session;
-use rustc::session::config::{self, Input, OutputFilenames};
+use rustc::session::config::{self, Input, OutputFilenames, OutputType};
 use rustc::session::search_paths::PathKind;
 use rustc::lint;
 use rustc::metadata;
@@ -31,20 +31,22 @@ use rustc_trans::trans;
 use rustc_typeck as typeck;
 use rustc_privacy;
 use rustc_front::hir;
-use rustc_front::lowering::lower_crate;
+use rustc_front::lowering::{lower_crate, LoweringContext};
 use super::Compilation;
 
 use serialize::json;
 
+use std::collections::HashMap;
 use std::env;
 use std::ffi::{OsString, OsStr};
 use std::fs;
 use std::io::{self, Write};
 use std::path::{Path, PathBuf};
-use syntax::ast;
+use syntax::ast::{self, NodeIdAssigner};
 use syntax::attr;
 use syntax::attr::AttrMetaMethods;
 use syntax::diagnostics;
+use syntax::feature_gate::UnstableFeatures;
 use syntax::fold::Folder;
 use syntax::parse;
 use syntax::parse::token;
@@ -70,7 +72,7 @@ pub fn compile_input(sess: Session,
     // We need nested scopes here, because the intermediate results can keep
     // large chunks of memory alive and we want to free them as soon as
     // possible to keep the peak memory usage low
-    let (sess, result) = {
+    let result = {
         let (outputs, expanded_crate, id) = {
             let krate = phase_1_parse_input(&sess, cfg, input);
 
@@ -111,13 +113,14 @@ pub fn compile_input(sess: Session,
 
         let expanded_crate = assign_node_ids(&sess, expanded_crate);
         // Lower ast -> hir.
+        let lcx = LoweringContext::new(&sess, Some(&expanded_crate));
         let mut hir_forest = time(sess.time_passes(),
                                   "lowering ast -> hir",
-                                  || hir_map::Forest::new(lower_crate(&expanded_crate)));
+                                  || hir_map::Forest::new(lower_crate(&lcx, &expanded_crate)));
         let arenas = ty::CtxtArenas::new();
         let ast_map = make_map(&sess, &mut hir_forest);
 
-        write_out_deps(&sess, input, &outputs, &id[..]);
+        write_out_deps(&sess, &outputs, &id);
 
         controller_entry_point!(after_write_deps,
                                 sess,
@@ -127,14 +130,21 @@ pub fn compile_input(sess: Session,
                                                                      &ast_map,
                                                                      &expanded_crate,
                                                                      &ast_map.krate(),
-                                                                     &id[..]));
+                                                                     &id[..],
+                                                                     &lcx));
 
+        time(sess.time_passes(), "attribute checking", || {
+            front::check_attr::check_crate(&sess, &expanded_crate);
+        });
+
+        time(sess.time_passes(), "early lint checks", || {
+            lint::check_ast_crate(&sess, &expanded_crate)
+        });
 
-        phase_3_run_analysis_passes(sess,
+        phase_3_run_analysis_passes(&sess,
                                     ast_map,
-                                    &expanded_crate,
                                     &arenas,
-                                    id,
+                                    &id,
                                     control.make_glob_map,
                                     |tcx, analysis| {
 
@@ -145,7 +155,9 @@ pub fn compile_input(sess: Session,
                                                                &expanded_crate,
                                                                tcx.map.krate(),
                                                                &analysis,
-                                                               tcx);
+                                                               tcx,
+                                                               &lcx,
+                                                               &id);
                 (control.after_analysis.callback)(state);
 
                 tcx.sess.abort_if_errors();
@@ -269,8 +281,9 @@ pub struct CompileState<'a, 'ast: 'a, 'tcx: 'a> {
     pub expanded_crate: Option<&'a ast::Crate>,
     pub hir_crate: Option<&'a hir::Crate>,
     pub ast_map: Option<&'a hir_map::Map<'ast>>,
-    pub analysis: Option<&'a ty::CrateAnalysis>,
+    pub analysis: Option<&'a ty::CrateAnalysis<'a>>,
     pub tcx: Option<&'a ty::ctxt<'tcx>>,
+    pub lcx: Option<&'a LoweringContext<'a>>,
     pub trans: Option<&'a trans::CrateTranslation>,
 }
 
@@ -292,6 +305,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
             ast_map: None,
             analysis: None,
             tcx: None,
+            lcx: None,
             trans: None,
         }
     }
@@ -326,13 +340,15 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
                               ast_map: &'a hir_map::Map<'ast>,
                               krate: &'a ast::Crate,
                               hir_crate: &'a hir::Crate,
-                              crate_name: &'a str)
+                              crate_name: &'a str,
+                              lcx: &'a LoweringContext<'a>)
                               -> CompileState<'a, 'ast, 'tcx> {
         CompileState {
             crate_name: Some(crate_name),
             ast_map: Some(ast_map),
             krate: Some(krate),
             hir_crate: Some(hir_crate),
+            lcx: Some(lcx),
             .. CompileState::empty(input, session, out_dir)
         }
     }
@@ -343,13 +359,17 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
                             krate: &'a ast::Crate,
                             hir_crate: &'a hir::Crate,
                             analysis: &'a ty::CrateAnalysis,
-                            tcx: &'a ty::ctxt<'tcx>)
+                            tcx: &'a ty::ctxt<'tcx>,
+                            lcx: &'a LoweringContext<'a>,
+                            crate_name: &'a str)
                             -> CompileState<'a, 'ast, 'tcx> {
         CompileState {
             analysis: Some(analysis),
             tcx: Some(tcx),
             krate: Some(krate),
             hir_crate: Some(hir_crate),
+            lcx: Some(lcx),
+            crate_name: Some(crate_name),
             .. CompileState::empty(input, session, out_dir)
         }
     }
@@ -480,13 +500,16 @@ pub fn phase_2_configure_and_expand(sess: &Session,
         }
     });
 
-    let Registry { syntax_exts, lint_passes, lint_groups,
+    let Registry { syntax_exts, early_lint_passes, late_lint_passes, lint_groups,
                    llvm_passes, attributes, .. } = registry;
 
     {
         let mut ls = sess.lint_store.borrow_mut();
-        for pass in lint_passes {
-            ls.register_pass(Some(sess), true, pass);
+        for pass in early_lint_passes {
+            ls.register_early_pass(Some(sess), true, pass);
+        }
+        for pass in late_lint_passes {
+            ls.register_late_pass(Some(sess), true, pass);
         }
 
         for (name, to) in lint_groups {
@@ -639,14 +662,13 @@ pub fn make_map<'ast>(sess: &Session,
 /// Run the resolution, typechecking, region checking and other
 /// miscellaneous analysis passes on the crate. Return various
 /// structures carrying the results of the analysis.
-pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session,
+pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                                                ast_map: front::map::Map<'tcx>,
-                                               ast_crate: &ast::Crate,
                                                arenas: &'tcx ty::CtxtArenas<'tcx>,
-                                               name: String,
+                                               name: &str,
                                                make_glob_map: resolve::MakeGlobMap,
                                                f: F)
-                                               -> (Session, R)
+                                               -> R
                                                where F: for<'a> FnOnce(&'a ty::ctxt<'tcx>,
                                                                        ty::CrateAnalysis) -> R
 {
@@ -654,10 +676,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session,
     let krate = ast_map.krate();
 
     time(time_passes, "external crate/lib resolution", ||
-         LocalCrateReader::new(&sess, &ast_map).read_crates(krate));
+         LocalCrateReader::new(sess, &ast_map).read_crates(krate));
 
     let lang_items = time(time_passes, "language item collection", ||
-                          middle::lang_items::collect_language_items(krate, &sess));
+                          middle::lang_items::collect_language_items(&sess, &ast_map));
 
     let resolve::CrateMap {
         def_map,
@@ -668,16 +690,19 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session,
         glob_map,
     } =
         time(time_passes, "resolution",
-             || resolve::resolve_crate(&sess, &ast_map, make_glob_map));
+             || resolve::resolve_crate(sess, &ast_map, make_glob_map));
 
     // Discard MTWT tables that aren't required past resolution.
-    syntax::ext::mtwt::clear_tables();
+    // FIXME: get rid of uses of MTWT tables in typeck, mir and trans and clear them
+    if !sess.opts.debugging_opts.keep_mtwt_tables {
+        // syntax::ext::mtwt::clear_tables();
+    }
 
     let named_region_map = time(time_passes, "lifetime resolution",
-                                || middle::resolve_lifetime::krate(&sess, krate, &def_map));
+                                || middle::resolve_lifetime::krate(sess, krate, &def_map));
 
     time(time_passes, "looking for entry point",
-         || middle::entry::find_entry_point(&sess, &ast_map));
+         || middle::entry::find_entry_point(sess, &ast_map));
 
     sess.plugin_registrar_fn.set(
         time(time_passes, "looking for plugin registrar", ||
@@ -685,13 +710,13 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session,
                 sess.diagnostic(), krate)));
 
     let region_map = time(time_passes, "region resolution", ||
-                          middle::region::resolve_crate(&sess, krate));
+                          middle::region::resolve_crate(sess, krate));
 
     time(time_passes, "loop checking", ||
-         middle::check_loop::check_crate(&sess, krate));
+         middle::check_loop::check_crate(sess, krate));
 
     time(time_passes, "static item recursion checking", ||
-         middle::check_static_recursion::check_crate(&sess, krate, &def_map, &ast_map));
+         middle::check_static_recursion::check_crate(sess, krate, &def_map, &ast_map));
 
     ty::ctxt::create_and_enter(sess,
                                arenas,
@@ -707,9 +732,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session,
         // passes are timed inside typeck
         typeck::check_crate(tcx, trait_map);
 
-        time(time_passes, "MIR dump", ||
-             mir::dump::dump_crate(tcx));
-
         time(time_passes, "const checking", ||
             middle::check_const::check_crate(tcx));
 
@@ -730,6 +752,19 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session,
         time(time_passes, "match checking", ||
             middle::check_match::check_crate(tcx));
 
+        match tcx.sess.opts.unstable_features {
+            UnstableFeatures::Disallow => {
+                // use this as a shorthand for beta/stable, and skip
+                // MIR construction there until known regressions are
+                // addressed
+            }
+            UnstableFeatures::Allow | UnstableFeatures::Cheat => {
+                let _mir_map =
+                    time(time_passes, "MIR dump", ||
+                            mir::mir_map::build_mir_for_crate(tcx));
+            }
+        }
+
         time(time_passes, "liveness checking", ||
             middle::liveness::check_crate(tcx));
 
@@ -765,7 +800,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session,
                 &tcx.sess, lib_features_used));
 
         time(time_passes, "lint checking", ||
-            lint::check_crate(tcx, &lower_crate(ast_crate), &exported_items));
+            lint::check_crate(tcx, krate, &exported_items));
 
         // The above three passes generate errors w/o aborting
         tcx.sess.abort_if_errors();
@@ -801,16 +836,16 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
                                trans: &trans::CrateTranslation,
                                outputs: &OutputFilenames) {
     if sess.opts.cg.no_integrated_as {
-        let output_type = config::OutputTypeAssembly;
-
+        let mut map = HashMap::new();
+        map.insert(OutputType::Assembly, None);
         time(sess.time_passes(), "LLVM passes", ||
-            write::run_passes(sess, trans, &[output_type], outputs));
+            write::run_passes(sess, trans, &map, outputs));
 
         write::run_assembler(sess, outputs);
 
         // Remove assembly source, unless --save-temps was specified
         if !sess.opts.cg.save_temps {
-            fs::remove_file(&outputs.temp_path(config::OutputTypeAssembly)).unwrap();
+            fs::remove_file(&outputs.temp_path(OutputType::Assembly)).unwrap();
         }
     } else {
         time(sess.time_passes(), "LLVM passes", ||
@@ -841,16 +876,12 @@ fn escape_dep_filename(filename: &str) -> String {
     filename.replace(" ", "\\ ")
 }
 
-fn write_out_deps(sess: &Session,
-                  input: &Input,
-                  outputs: &OutputFilenames,
-                  id: &str) {
-
+fn write_out_deps(sess: &Session, outputs: &OutputFilenames, id: &str) {
     let mut out_filenames = Vec::new();
-    for output_type in &sess.opts.output_types {
+    for output_type in sess.opts.output_types.keys() {
         let file = outputs.path(*output_type);
         match *output_type {
-            config::OutputTypeExe => {
+            OutputType::Exe => {
                 for output in sess.crate_types.borrow().iter() {
                     let p = link::filename_for_input(sess, *output, id,
                                                      outputs);
@@ -861,23 +892,11 @@ fn write_out_deps(sess: &Session,
         }
     }
 
-    // Write out dependency rules to the dep-info file if requested with
-    // --dep-info
-    let deps_filename = match sess.opts.write_dependency_info {
-        // Use filename from --dep-file argument if given
-        (true, Some(ref filename)) => filename.clone(),
-        // Use default filename: crate source filename with extension replaced
-        // by ".d"
-        (true, None) => match *input {
-            Input::File(..) => outputs.with_extension("d"),
-            Input::Str(..) => {
-                sess.warn("can not write --dep-info without a filename \
-                           when compiling stdin.");
-                return
-            },
-        },
-        _ => return,
-    };
+    // Write out dependency rules to the dep-info file if requested
+    if !sess.opts.output_types.contains_key(&OutputType::DepInfo) {
+        return
+    }
+    let deps_filename = outputs.path(OutputType::DepInfo);
 
     let result = (|| -> io::Result<()> {
         // Build a list of files used to compile the output and
@@ -890,9 +909,16 @@ fn write_out_deps(sess: &Session,
                                    .collect();
         let mut file = try!(fs::File::create(&deps_filename));
         for path in &out_filenames {
-            try!(write!(&mut file,
+            try!(write!(file,
                         "{}: {}\n\n", path.display(), files.join(" ")));
         }
+
+        // Emit a fake target for each input file to the compilation. This
+        // prevents `make` from spitting out an error if a file is later
+        // deleted. For more info see #28735
+        for path in files {
+            try!(writeln!(file, "{}:", path));
+        }
         Ok(())
     })();
 
@@ -1006,11 +1032,15 @@ pub fn build_output_filenames(input: &Input,
                 out_filestem: stem,
                 single_output_file: None,
                 extra: sess.opts.cg.extra_filename.clone(),
+                outputs: sess.opts.output_types.clone(),
             }
         }
 
         Some(ref out_file) => {
-            let ofile = if sess.opts.output_types.len() > 1 {
+            let unnamed_output_types = sess.opts.output_types.values()
+                                           .filter(|a| a.is_none())
+                                           .count();
+            let ofile = if unnamed_output_types > 1 {
                 sess.warn("ignoring specified output filename because multiple \
                            outputs were requested");
                 None
@@ -1029,6 +1059,7 @@ pub fn build_output_filenames(input: &Input,
                                       .to_str().unwrap().to_string(),
                 single_output_file: ofile,
                 extra: sess.opts.cg.extra_filename.clone(),
+                outputs: sess.opts.output_types.clone(),
             }
         }
     }
index 7d9c74fe48702d74b1f6900f2b25ee0bec600111..ce40d9b53ff0a66ff864fcf94a7ddc9338b21f8f 100644 (file)
@@ -63,7 +63,7 @@ use rustc_resolve as resolve;
 use rustc_trans::back::link;
 use rustc_trans::save;
 use rustc::session::{config, Session, build_session};
-use rustc::session::config::{Input, PrintRequest};
+use rustc::session::config::{Input, PrintRequest, OutputType};
 use rustc::lint::Lint;
 use rustc::lint;
 use rustc::metadata;
@@ -285,7 +285,12 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
                       -> Compilation {
         match matches.opt_str("explain") {
             Some(ref code) => {
-                match descriptions.find_description(&code[..]) {
+                let normalised = if !code.starts_with("E") {
+                    format!("E{0:0>4}", code)
+                } else {
+                    code.to_string()
+                };
+                match descriptions.find_description(&normalised) {
                     Some(ref description) => {
                         // Slice off the leading newline and print.
                         print!("{}", &description[1..]);
@@ -382,7 +387,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
             control.after_analysis.stop = Compilation::Stop;
         }
 
-        if !sess.opts.output_types.iter().any(|&i| i == config::OutputTypeExe) {
+        if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe) {
             control.after_llvm.stop = Compilation::Stop;
         }
 
@@ -391,8 +396,10 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
                 time(state.session.time_passes(),
                      "save analysis",
                      || save::process_crate(state.tcx.unwrap(),
+                                            state.lcx.unwrap(),
                                             state.krate.unwrap(),
                                             state.analysis.unwrap(),
+                                            state.crate_name.unwrap(),
                                             state.out_dir));
             };
             control.make_glob_map = resolve::MakeGlobMap::Yes;
index 989a586cee93de9cf1648aa985d49aaadbef39c0..a30c437197c3b1e930fba1dfb148a78e7f667290 100644 (file)
@@ -32,6 +32,7 @@ use syntax::ast;
 use syntax::codemap;
 use syntax::fold::{self, Folder};
 use syntax::print::{pp, pprust};
+use syntax::print::pprust::PrintState;
 use syntax::ptr::P;
 use syntax::util::small_vector::SmallVector;
 
@@ -46,7 +47,7 @@ use std::str::FromStr;
 use rustc::front::map as hir_map;
 use rustc::front::map::{blocks, NodePrinter};
 use rustc_front::hir;
-use rustc_front::lowering::lower_crate;
+use rustc_front::lowering::{lower_crate, LoweringContext};
 use rustc_front::print::pprust as pprust_hir;
 
 #[derive(Copy, Clone, PartialEq, Debug)]
@@ -130,7 +131,7 @@ pub fn parse_pretty(sess: &Session,
 impl PpSourceMode {
     /// Constructs a `PrinterSupport` object and passes it to `f`.
     fn call_with_pp_support<'tcx, A, B, F>(&self,
-                                           sess: Session,
+                                           sess: &'tcx Session,
                                            ast_map: Option<hir_map::Map<'tcx>>,
                                            payload: B,
                                            f: F) -> A where
@@ -154,11 +155,10 @@ impl PpSourceMode {
         }
     }
     fn call_with_pp_support_hir<'tcx, A, B, F>(&self,
-                                               sess: Session,
+                                               sess: &'tcx Session,
                                                ast_map: &hir_map::Map<'tcx>,
-                                               ast_crate: &ast::Crate,
                                                arenas: &'tcx ty::CtxtArenas<'tcx>,
-                                               id: String,
+                                               id: &str,
                                                payload: B,
                                                f: F) -> A where
         F: FnOnce(&HirPrinterSupport, B, &hir::Crate) -> A,
@@ -179,14 +179,13 @@ impl PpSourceMode {
             PpmTyped => {
                 driver::phase_3_run_analysis_passes(sess,
                                                     ast_map.clone(),
-                                                    ast_crate,
                                                     arenas,
                                                     id,
                                                     resolve::MakeGlobMap::No,
                                                     |tcx, _| {
                     let annotation = TypedAnnotation { tcx: tcx };
                     f(&annotation, payload, &ast_map.forest.krate)
-                }).1
+                })
             }
             _ => panic!("Should use call_with_pp_support"),
         }
@@ -226,12 +225,12 @@ trait HirPrinterSupport<'ast>: pprust_hir::PpAnn {
 }
 
 struct NoAnn<'ast> {
-    sess: Session,
+    sess: &'ast Session,
     ast_map: Option<hir_map::Map<'ast>>
 }
 
 impl<'ast> PrinterSupport<'ast> for NoAnn<'ast> {
-    fn sess<'a>(&'a self) -> &'a Session { &self.sess }
+    fn sess<'a>(&'a self) -> &'a Session { self.sess }
 
     fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> {
         self.ast_map.as_ref()
@@ -241,7 +240,7 @@ impl<'ast> PrinterSupport<'ast> for NoAnn<'ast> {
 }
 
 impl<'ast> HirPrinterSupport<'ast> for NoAnn<'ast> {
-    fn sess<'a>(&'a self) -> &'a Session { &self.sess }
+    fn sess<'a>(&'a self) -> &'a Session { self.sess }
 
     fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> {
         self.ast_map.as_ref()
@@ -254,12 +253,12 @@ impl<'ast> pprust::PpAnn for NoAnn<'ast> {}
 impl<'ast> pprust_hir::PpAnn for NoAnn<'ast> {}
 
 struct IdentifiedAnnotation<'ast> {
-    sess: Session,
+    sess: &'ast Session,
     ast_map: Option<hir_map::Map<'ast>>,
 }
 
 impl<'ast> PrinterSupport<'ast> for IdentifiedAnnotation<'ast> {
-    fn sess<'a>(&'a self) -> &'a Session { &self.sess }
+    fn sess<'a>(&'a self) -> &'a Session { self.sess }
 
     fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> {
         self.ast_map.as_ref()
@@ -309,7 +308,7 @@ impl<'ast> pprust::PpAnn for IdentifiedAnnotation<'ast> {
 }
 
 impl<'ast> HirPrinterSupport<'ast> for IdentifiedAnnotation<'ast> {
-    fn sess<'a>(&'a self) -> &'a Session { &self.sess }
+    fn sess<'a>(&'a self) -> &'a Session { self.sess }
 
     fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> {
         self.ast_map.as_ref()
@@ -331,8 +330,7 @@ impl<'ast> pprust_hir::PpAnn for IdentifiedAnnotation<'ast> {
             s: &mut pprust_hir::State,
             node: pprust_hir::AnnNode) -> io::Result<()> {
         match node {
-            pprust_hir::NodeIdent(_) | pprust_hir::NodeName(_) => Ok(()),
-
+            pprust_hir::NodeName(_) => Ok(()),
             pprust_hir::NodeItem(item) => {
                 try!(pp::space(&mut s.s));
                 s.synth_comment(item.id.to_string())
@@ -359,12 +357,12 @@ impl<'ast> pprust_hir::PpAnn for IdentifiedAnnotation<'ast> {
 }
 
 struct HygieneAnnotation<'ast> {
-    sess: Session,
+    sess: &'ast Session,
     ast_map: Option<hir_map::Map<'ast>>,
 }
 
 impl<'ast> PrinterSupport<'ast> for HygieneAnnotation<'ast> {
-    fn sess<'a>(&'a self) -> &'a Session { &self.sess }
+    fn sess<'a>(&'a self) -> &'a Session { self.sess }
 
     fn ast_map<'a>(&'a self) -> Option<&'a hir_map::Map<'ast>> {
         self.ast_map.as_ref()
@@ -382,7 +380,7 @@ impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> {
                 try!(pp::space(&mut s.s));
                 // FIXME #16420: this doesn't display the connections
                 // between syntax contexts
-                s.synth_comment(format!("{}#{}", nm, ctxt))
+                s.synth_comment(format!("{}#{}", nm, ctxt.0))
             }
             pprust::NodeName(&ast::Name(nm)) => {
                 try!(pp::space(&mut s.s));
@@ -672,9 +670,10 @@ pub fn pretty_print_input(sess: Session,
     // There is some twisted, god-forsaken tangle of lifetimes here which makes
     // the ordering of stuff super-finicky.
     let mut hir_forest;
+    let lcx = LoweringContext::new(&sess, Some(&krate));
     let arenas = ty::CtxtArenas::new();
     let ast_map = if compute_ast_map {
-        hir_forest = hir_map::Forest::new(lower_crate(&krate));
+        hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate));
         let map = driver::make_map(&sess, &mut hir_forest);
         Some(map)
     } else {
@@ -697,7 +696,7 @@ pub fn pretty_print_input(sess: Session,
             // Silently ignores an identified node.
             let out: &mut Write = &mut out;
             s.call_with_pp_support(
-                sess, ast_map, box out, |annotation, out| {
+                &sess, ast_map, box out, |annotation, out| {
                     debug!("pretty printing source code {:?}", s);
                     let sess = annotation.sess();
                     pprust::print_crate(sess.codemap(),
@@ -714,7 +713,7 @@ pub fn pretty_print_input(sess: Session,
         (PpmHir(s), None) => {
             let out: &mut Write = &mut out;
             s.call_with_pp_support_hir(
-                sess, &ast_map.unwrap(), &krate, &arenas, id, box out, |annotation, out, krate| {
+                &sess, &ast_map.unwrap(), &arenas, &id, box out, |annotation, out, krate| {
                     debug!("pretty printing source code {:?}", s);
                     let sess = annotation.sess();
                     pprust_hir::print_crate(sess.codemap(),
@@ -730,11 +729,10 @@ pub fn pretty_print_input(sess: Session,
 
         (PpmHir(s), Some(uii)) => {
             let out: &mut Write = &mut out;
-            s.call_with_pp_support_hir(sess,
+            s.call_with_pp_support_hir(&sess,
                                        &ast_map.unwrap(),
-                                       &krate,
                                        &arenas,
-                                       id,
+                                       &id,
                                        (out,uii),
                                        |annotation, (out,uii), _| {
                 debug!("pretty printing source code {:?}", s);
@@ -779,15 +777,14 @@ pub fn pretty_print_input(sess: Session,
             match code {
                 Some(code) => {
                     let variants = gather_flowgraph_variants(&sess);
-                    driver::phase_3_run_analysis_passes(sess,
+                    driver::phase_3_run_analysis_passes(&sess,
                                                         ast_map,
-                                                        &krate,
                                                         &arenas,
-                                                        id,
+                                                        &id,
                                                         resolve::MakeGlobMap::No,
                                                         |tcx, _| {
                         print_flowgraph(variants, tcx, code, mode, out)
-                    }).1
+                    })
                 }
                 None => {
                     let message = format!("--pretty=flowgraph needs \
index 96d9572b4859178854dde6ce2eefa11371385904..4bbc22ef1a273d87bcaf3bfa55ab082ebd24b74b 100644 (file)
@@ -38,7 +38,7 @@ use syntax::diagnostic::{Level, RenderSpan, Bug, Fatal, Error, Warning, Note, He
 use syntax::parse::token;
 use syntax::feature_gate::UnstableFeatures;
 
-use rustc_front::lowering::lower_crate;
+use rustc_front::lowering::{lower_crate, LoweringContext};
 use rustc_front::hir;
 
 struct Env<'a, 'tcx: 'a> {
@@ -124,18 +124,19 @@ fn test_env<F>(source_string: &str,
                     .expect("phase 2 aborted");
 
     let krate = driver::assign_node_ids(&sess, krate);
-    let mut hir_forest = hir_map::Forest::new(lower_crate(&krate));
+    let lcx = LoweringContext::new(&sess, Some(&krate));
+    let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate));
     let arenas = ty::CtxtArenas::new();
     let ast_map = driver::make_map(&sess, &mut hir_forest);
     let krate = ast_map.krate();
 
     // run just enough stuff to build a tcx:
-    let lang_items = lang_items::collect_language_items(krate, &sess);
+    let lang_items = lang_items::collect_language_items(&sess, &ast_map);
     let resolve::CrateMap { def_map, freevars, .. } =
         resolve::resolve_crate(&sess, &ast_map, resolve::MakeGlobMap::No);
     let named_region_map = resolve_lifetime::krate(&sess, krate, &def_map);
     let region_map = region::resolve_crate(&sess, krate);
-    ty::ctxt::create_and_enter(sess,
+    ty::ctxt::create_and_enter(&sess,
                                &arenas,
                                def_map,
                                named_region_map,
@@ -195,7 +196,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
                       -> Option<ast::NodeId> {
             assert!(idx < names.len());
             for item in &m.items {
-                if item.ident.to_string() == names[idx] {
+                if item.name.to_string() == names[idx] {
                     return search(this, &**item, idx+1, names);
                 }
             }
@@ -295,7 +296,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
     {
         let name = token::intern(name);
         ty::ReEarlyBound(ty::EarlyBoundRegion {
-            param_id: ast::DUMMY_NODE_ID,
+            def_id: self.infcx.tcx.map.local_def_id(ast::DUMMY_NODE_ID),
             space: space,
             index: index,
             name: name
@@ -350,6 +351,11 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
                                    self.tcx().types.isize)
     }
 
+    pub fn t_rptr_empty(&self) -> Ty<'tcx> {
+        self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(ty::ReEmpty),
+                                   self.tcx().types.isize)
+    }
+
     pub fn dummy_type_trace(&self) -> infer::TypeTrace<'tcx> {
         infer::TypeTrace::dummy(self.tcx())
     }
@@ -592,16 +598,15 @@ fn lub_free_free() {
 
 #[test]
 fn lub_returning_scope() {
-    test_env(EMPTY_SOURCE_STR,
-             errors(&["cannot infer an appropriate lifetime"]), |env| {
-                 env.create_simple_region_hierarchy();
-                 let t_rptr_scope10 = env.t_rptr_scope(10);
-                 let t_rptr_scope11 = env.t_rptr_scope(11);
-
-                 // this should generate an error when regions are resolved
-                 env.make_lub_ty(env.t_fn(&[], t_rptr_scope10),
-                                 env.t_fn(&[], t_rptr_scope11));
-             })
+    test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
+        env.create_simple_region_hierarchy();
+        let t_rptr_scope10 = env.t_rptr_scope(10);
+        let t_rptr_scope11 = env.t_rptr_scope(11);
+        let t_rptr_empty = env.t_rptr_empty();
+        env.check_lub(env.t_fn(&[t_rptr_scope10], env.tcx().types.isize),
+                      env.t_fn(&[t_rptr_scope11], env.tcx().types.isize),
+                      env.t_fn(&[t_rptr_empty], env.tcx().types.isize));
+    });
 }
 
 #[test]
diff --git a/src/librustc_front/attr.rs b/src/librustc_front/attr.rs
deleted file mode 100644 (file)
index 8609fd9..0000000
+++ /dev/null
@@ -1,628 +0,0 @@
-// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Functions dealing with attributes and meta items
-
-pub use self::StabilityLevel::*;
-pub use self::ReprAttr::*;
-pub use self::IntType::*;
-
-use hir;
-use hir::{AttrId, Attribute, Attribute_, MetaItem, MetaWord, MetaNameValue, MetaList};
-use lowering::{lower_attr_style, unlower_attribute};
-use syntax::codemap::{Span, Spanned, spanned, dummy_spanned};
-use syntax::codemap::BytePos;
-use syntax::diagnostic::SpanHandler;
-use syntax::attr as syntax_attr;
-use syntax::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
-use syntax::parse::token::{InternedString, intern_and_get_ident};
-use syntax::parse::token;
-use syntax::ptr::P;
-
-use std::cell::Cell;
-use std::collections::HashSet;
-use std::fmt;
-
-pub fn mark_used(attr: &Attribute) {
-    syntax_attr::mark_used(&unlower_attribute(attr))
-}
-
-pub trait AttrMetaMethods {
-    fn check_name(&self, name: &str) -> bool {
-        name == &self.name()[..]
-    }
-
-    /// Retrieve the name of the meta item, e.g. `foo` in `#[foo]`,
-    /// `#[foo="bar"]` and `#[foo(bar)]`
-    fn name(&self) -> InternedString;
-
-    /// Gets the string value if self is a MetaNameValue variant
-    /// containing a string, otherwise None.
-    fn value_str(&self) -> Option<InternedString>;
-    /// Gets a list of inner meta items from a list MetaItem type.
-    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<MetaItem>]>;
-
-    fn span(&self) -> Span;
-}
-
-impl AttrMetaMethods for Attribute {
-    fn check_name(&self, name: &str) -> bool {
-        let matches = name == &self.name()[..];
-        if matches {
-            syntax_attr::mark_used(&unlower_attribute(self));
-        }
-        matches
-    }
-    fn name(&self) -> InternedString { self.meta().name() }
-    fn value_str(&self) -> Option<InternedString> {
-        self.meta().value_str()
-    }
-    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<MetaItem>]> {
-        self.node.value.meta_item_list()
-    }
-    fn span(&self) -> Span { self.meta().span }
-}
-
-impl AttrMetaMethods for MetaItem {
-    fn name(&self) -> InternedString {
-        match self.node {
-            MetaWord(ref n) => (*n).clone(),
-            MetaNameValue(ref n, _) => (*n).clone(),
-            MetaList(ref n, _) => (*n).clone(),
-        }
-    }
-
-    fn value_str(&self) -> Option<InternedString> {
-        match self.node {
-            MetaNameValue(_, ref v) => {
-                match v.node {
-                    hir::LitStr(ref s, _) => Some((*s).clone()),
-                    _ => None,
-                }
-            },
-            _ => None
-        }
-    }
-
-    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<MetaItem>]> {
-        match self.node {
-            MetaList(_, ref l) => Some(&l[..]),
-            _ => None
-        }
-    }
-    fn span(&self) -> Span { self.span }
-}
-
-// Annoying, but required to get test_cfg to work
-impl AttrMetaMethods for P<MetaItem> {
-    fn name(&self) -> InternedString { (**self).name() }
-    fn value_str(&self) -> Option<InternedString> { (**self).value_str() }
-    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<MetaItem>]> {
-        (**self).meta_item_list()
-    }
-    fn span(&self) -> Span { (**self).span() }
-}
-
-
-pub trait AttributeMethods {
-    fn meta<'a>(&'a self) -> &'a MetaItem;
-    fn with_desugared_doc<T, F>(&self, f: F) -> T where
-        F: FnOnce(&Attribute) -> T;
-}
-
-impl AttributeMethods for Attribute {
-    /// Extract the MetaItem from inside this Attribute.
-    fn meta<'a>(&'a self) -> &'a MetaItem {
-        &*self.node.value
-    }
-
-    /// Convert self to a normal #[doc="foo"] comment, if it is a
-    /// comment like `///` or `/** */`. (Returns self unchanged for
-    /// non-sugared doc attributes.)
-    fn with_desugared_doc<T, F>(&self, f: F) -> T where
-        F: FnOnce(&Attribute) -> T,
-    {
-        if self.node.is_sugared_doc {
-            let comment = self.value_str().unwrap();
-            let meta = mk_name_value_item_str(
-                InternedString::new("doc"),
-                token::intern_and_get_ident(&strip_doc_comment_decoration(
-                        &comment)));
-            if self.node.style == hir::AttrOuter {
-                f(&mk_attr_outer(self.node.id, meta))
-            } else {
-                f(&mk_attr_inner(self.node.id, meta))
-            }
-        } else {
-            f(self)
-        }
-    }
-}
-
-/* Constructors */
-
-pub fn mk_name_value_item_str(name: InternedString, value: InternedString)
-                              -> P<MetaItem> {
-    let value_lit = dummy_spanned(hir::LitStr(value, hir::CookedStr));
-    mk_name_value_item(name, value_lit)
-}
-
-pub fn mk_name_value_item(name: InternedString, value: hir::Lit)
-                          -> P<MetaItem> {
-    P(dummy_spanned(MetaNameValue(name, value)))
-}
-
-pub fn mk_list_item(name: InternedString, items: Vec<P<MetaItem>>) -> P<MetaItem> {
-    P(dummy_spanned(MetaList(name, items)))
-}
-
-pub fn mk_word_item(name: InternedString) -> P<MetaItem> {
-    P(dummy_spanned(MetaWord(name)))
-}
-
-thread_local! { static NEXT_ATTR_ID: Cell<usize> = Cell::new(0) }
-
-pub fn mk_attr_id() -> AttrId {
-    let id = NEXT_ATTR_ID.with(|slot| {
-        let r = slot.get();
-        slot.set(r + 1);
-        r
-    });
-    AttrId(id)
-}
-
-/// Returns an inner attribute with the given value.
-pub fn mk_attr_inner(id: AttrId, item: P<MetaItem>) -> Attribute {
-    dummy_spanned(Attribute_ {
-        id: id,
-        style: hir::AttrInner,
-        value: item,
-        is_sugared_doc: false,
-    })
-}
-
-/// Returns an outer attribute with the given value.
-pub fn mk_attr_outer(id: AttrId, item: P<MetaItem>) -> Attribute {
-    dummy_spanned(Attribute_ {
-        id: id,
-        style: hir::AttrOuter,
-        value: item,
-        is_sugared_doc: false,
-    })
-}
-
-pub fn mk_sugared_doc_attr(id: AttrId, text: InternedString, lo: BytePos,
-                           hi: BytePos)
-                           -> Attribute {
-    let style = lower_attr_style(doc_comment_style(&text));
-    let lit = spanned(lo, hi, hir::LitStr(text, hir::CookedStr));
-    let attr = Attribute_ {
-        id: id,
-        style: style,
-        value: P(spanned(lo, hi, MetaNameValue(InternedString::new("doc"),
-                                               lit))),
-        is_sugared_doc: true
-    };
-    spanned(lo, hi, attr)
-}
-
-/* Searching */
-/// Check if `needle` occurs in `haystack` by a structural
-/// comparison. This is slightly subtle, and relies on ignoring the
-/// span included in the `==` comparison a plain MetaItem.
-pub fn contains(haystack: &[P<MetaItem>], needle: &MetaItem) -> bool {
-    debug!("attr::contains (name={})", needle.name());
-    haystack.iter().any(|item| {
-        debug!("  testing: {}", item.name());
-        item.node == needle.node
-    })
-}
-
-pub fn contains_name<AM: AttrMetaMethods>(metas: &[AM], name: &str) -> bool {
-    debug!("attr::contains_name (name={})", name);
-    metas.iter().any(|item| {
-        debug!("  testing: {}", item.name());
-        item.check_name(name)
-    })
-}
-
-pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: &str)
-                                 -> Option<InternedString> {
-    attrs.iter()
-        .find(|at| at.check_name(name))
-        .and_then(|at| at.value_str())
-}
-
-pub fn last_meta_item_value_str_by_name(items: &[P<MetaItem>], name: &str)
-                                     -> Option<InternedString> {
-    items.iter()
-         .rev()
-         .find(|mi| mi.check_name(name))
-         .and_then(|i| i.value_str())
-}
-
-/* Higher-level applications */
-
-pub fn sort_meta_items(items: Vec<P<MetaItem>>) -> Vec<P<MetaItem>> {
-    // This is sort of stupid here, but we need to sort by
-    // human-readable strings.
-    let mut v = items.into_iter()
-        .map(|mi| (mi.name(), mi))
-        .collect::<Vec<(InternedString, P<MetaItem>)>>();
-
-    v.sort_by(|&(ref a, _), &(ref b, _)| a.cmp(b));
-
-    // There doesn't seem to be a more optimal way to do this
-    v.into_iter().map(|(_, m)| m.map(|Spanned {node, span}| {
-        Spanned {
-            node: match node {
-                MetaList(n, mis) => MetaList(n, sort_meta_items(mis)),
-                _ => node
-            },
-            span: span
-        }
-    })).collect()
-}
-
-pub fn find_crate_name(attrs: &[Attribute]) -> Option<InternedString> {
-    first_attr_value_str_by_name(attrs, "crate_name")
-}
-
-/// Find the value of #[export_name=*] attribute and check its validity.
-pub fn find_export_name_attr(diag: &SpanHandler, attrs: &[Attribute]) -> Option<InternedString> {
-    attrs.iter().fold(None, |ia,attr| {
-        if attr.check_name("export_name") {
-            if let s@Some(_) = attr.value_str() {
-                s
-            } else {
-                diag.span_err(attr.span, "export_name attribute has invalid format");
-                diag.handler.help("use #[export_name=\"*\"]");
-                None
-            }
-        } else {
-            ia
-        }
-    })
-}
-
-#[derive(Copy, Clone, PartialEq)]
-pub enum InlineAttr {
-    None,
-    Hint,
-    Always,
-    Never,
-}
-
-/// Determine what `#[inline]` attribute is present in `attrs`, if any.
-pub fn find_inline_attr(diagnostic: Option<&SpanHandler>, attrs: &[Attribute]) -> InlineAttr {
-    // FIXME (#2809)---validate the usage of #[inline] and #[inline]
-    attrs.iter().fold(InlineAttr::None, |ia,attr| {
-        match attr.node.value.node {
-            MetaWord(ref n) if *n == "inline" => {
-                syntax_attr::mark_used(&unlower_attribute(attr));
-                InlineAttr::Hint
-            }
-            MetaList(ref n, ref items) if *n == "inline" => {
-                syntax_attr::mark_used(&unlower_attribute(attr));
-                if items.len() != 1 {
-                    diagnostic.map(|d|{ d.span_err(attr.span, "expected one argument"); });
-                    InlineAttr::None
-                } else if contains_name(&items[..], "always") {
-                    InlineAttr::Always
-                } else if contains_name(&items[..], "never") {
-                    InlineAttr::Never
-                } else {
-                    diagnostic.map(|d|{ d.span_err((*items[0]).span, "invalid argument"); });
-                    InlineAttr::None
-                }
-            }
-            _ => ia
-        }
-    })
-}
-
-/// True if `#[inline]` or `#[inline(always)]` is present in `attrs`.
-pub fn requests_inline(attrs: &[Attribute]) -> bool {
-    match find_inline_attr(None, attrs) {
-        InlineAttr::Hint | InlineAttr::Always => true,
-        InlineAttr::None | InlineAttr::Never => false,
-    }
-}
-
-/// Represents the #[deprecated] and friends attributes.
-#[derive(RustcEncodable, RustcDecodable, Clone, Debug, PartialEq, Eq, Hash)]
-pub struct Stability {
-    pub level: StabilityLevel,
-    pub feature: InternedString,
-    pub since: Option<InternedString>,
-    pub deprecated_since: Option<InternedString>,
-    // The reason for the current stability level. If deprecated, the
-    // reason for deprecation.
-    pub reason: Option<InternedString>,
-    // The relevant rust-lang issue
-    pub issue: Option<u32>
-}
-
-/// The available stability levels.
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Copy, Eq, Hash)]
-pub enum StabilityLevel {
-    Unstable,
-    Stable,
-}
-
-impl fmt::Display for StabilityLevel {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(self, f)
-    }
-}
-
-fn find_stability_generic<'a,
-                              AM: AttrMetaMethods,
-                              I: Iterator<Item=&'a AM>>
-                             (diagnostic: &SpanHandler, attrs: I, item_sp: Span)
-                             -> (Option<Stability>, Vec<&'a AM>) {
-
-    let mut stab: Option<Stability> = None;
-    let mut deprecated: Option<(Option<InternedString>, Option<InternedString>)> = None;
-    let mut used_attrs: Vec<&'a AM> = vec![];
-
-    'outer: for attr in attrs {
-        let tag = attr.name();
-        let tag = &tag[..];
-        if tag != "deprecated" && tag != "unstable" && tag != "stable" {
-            continue // not a stability level
-        }
-
-        used_attrs.push(attr);
-
-        let (feature, since, reason, issue) = match attr.meta_item_list() {
-            Some(metas) => {
-                let mut feature = None;
-                let mut since = None;
-                let mut reason = None;
-                let mut issue = None;
-                for meta in metas {
-                    match &*meta.name() {
-                        "feature" => {
-                            match meta.value_str() {
-                                Some(v) => feature = Some(v),
-                                None => {
-                                    diagnostic.span_err(meta.span, "incorrect meta item");
-                                    continue 'outer;
-                                }
-                            }
-                        }
-                        "since" => {
-                            match meta.value_str() {
-                                Some(v) => since = Some(v),
-                                None => {
-                                    diagnostic.span_err(meta.span, "incorrect meta item");
-                                    continue 'outer;
-                                }
-                            }
-                        }
-                        "reason" => {
-                            match meta.value_str() {
-                                Some(v) => reason = Some(v),
-                                None => {
-                                    diagnostic.span_err(meta.span, "incorrect meta item");
-                                    continue 'outer;
-                                }
-                            }
-                        }
-                        "issue" => {
-                            match meta.value_str().and_then(|s| s.parse().ok()) {
-                                Some(v) => issue = Some(v),
-                                None => {
-                                    diagnostic.span_err(meta.span, "incorrect meta item");
-                                    continue 'outer;
-                                }
-                            }
-                        }
-                        _ => {}
-                    }
-                }
-                (feature, since, reason, issue)
-            }
-            None => {
-                diagnostic.span_err(attr.span(), "incorrect stability attribute type");
-                continue
-            }
-        };
-
-        // Deprecated tags don't require feature names
-        if feature == None && tag != "deprecated" {
-            diagnostic.span_err(attr.span(), "missing 'feature'");
-        }
-
-        // Unstable tags don't require a version
-        if since == None && tag != "unstable" {
-            diagnostic.span_err(attr.span(), "missing 'since'");
-        }
-
-        if tag == "unstable" || tag == "stable" {
-            if stab.is_some() {
-                diagnostic.span_err(item_sp, "multiple stability levels");
-            }
-
-            let level = match tag {
-                "unstable" => Unstable,
-                "stable" => Stable,
-                _ => unreachable!()
-            };
-
-            stab = Some(Stability {
-                level: level,
-                feature: feature.unwrap_or(intern_and_get_ident("bogus")),
-                since: since,
-                deprecated_since: None,
-                reason: reason,
-                issue: issue,
-            });
-        } else { // "deprecated"
-            if deprecated.is_some() {
-                diagnostic.span_err(item_sp, "multiple deprecated attributes");
-            }
-
-            deprecated = Some((since, reason));
-        }
-    }
-
-    // Merge the deprecation info into the stability info
-    if deprecated.is_some() {
-        match stab {
-            Some(ref mut s) => {
-                let (since, reason) = deprecated.unwrap();
-                s.deprecated_since = since;
-                s.reason = reason;
-            }
-            None => {
-                diagnostic.span_err(item_sp, "deprecated attribute must be paired with \
-                                              either stable or unstable attribute");
-            }
-        }
-    } else if stab.as_ref().map_or(false, |s| s.level == Unstable && s.issue.is_none()) {
-        // non-deprecated unstable items need to point to issues.
-        diagnostic.span_err(item_sp,
-                            "non-deprecated unstable items need to point \
-                             to an issue with `issue = \"NNN\"`");
-    }
-
-    (stab, used_attrs)
-}
-
-/// Find the first stability attribute. `None` if none exists.
-pub fn find_stability(diagnostic: &SpanHandler, attrs: &[Attribute],
-                      item_sp: Span) -> Option<Stability> {
-    let (s, used) = find_stability_generic(diagnostic, attrs.iter(), item_sp);
-    for used in used { syntax_attr::mark_used(&unlower_attribute(used)) }
-    return s;
-}
-
-pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[P<MetaItem>]) {
-    let mut set = HashSet::new();
-    for meta in metas {
-        let name = meta.name();
-
-        if !set.insert(name.clone()) {
-            panic!(diagnostic.span_fatal(meta.span,
-                                  &format!("duplicate meta item `{}`", name)));
-        }
-    }
-}
-
-
-/// Parse #[repr(...)] forms.
-///
-/// Valid repr contents: any of the primitive integral type names (see
-/// `int_type_of_word`, below) to specify enum discriminant type; `C`, to use
-/// the same discriminant size that the corresponding C enum would or C
-/// structure layout, and `packed` to remove padding.
-pub fn find_repr_attrs(diagnostic: &SpanHandler, attr: &Attribute) -> Vec<ReprAttr> {
-    let mut acc = Vec::new();
-    match attr.node.value.node {
-        hir::MetaList(ref s, ref items) if *s == "repr" => {
-            syntax_attr::mark_used(&unlower_attribute(attr));
-            for item in items {
-                match item.node {
-                    hir::MetaWord(ref word) => {
-                        let hint = match &word[..] {
-                            // Can't use "extern" because it's not a lexical identifier.
-                            "C" => Some(ReprExtern),
-                            "packed" => Some(ReprPacked),
-                            "simd" => Some(ReprSimd),
-                            _ => match int_type_of_word(&word) {
-                                Some(ity) => Some(ReprInt(item.span, ity)),
-                                None => {
-                                    // Not a word we recognize
-                                    diagnostic.span_err(item.span,
-                                                        "unrecognized representation hint");
-                                    None
-                                }
-                            }
-                        };
-
-                        match hint {
-                            Some(h) => acc.push(h),
-                            None => { }
-                        }
-                    }
-                    // Not a word:
-                    _ => diagnostic.span_err(item.span, "unrecognized enum representation hint")
-                }
-            }
-        }
-        // Not a "repr" hint: ignore.
-        _ => { }
-    }
-    acc
-}
-
-fn int_type_of_word(s: &str) -> Option<IntType> {
-    match s {
-        "i8" => Some(SignedInt(hir::TyI8)),
-        "u8" => Some(UnsignedInt(hir::TyU8)),
-        "i16" => Some(SignedInt(hir::TyI16)),
-        "u16" => Some(UnsignedInt(hir::TyU16)),
-        "i32" => Some(SignedInt(hir::TyI32)),
-        "u32" => Some(UnsignedInt(hir::TyU32)),
-        "i64" => Some(SignedInt(hir::TyI64)),
-        "u64" => Some(UnsignedInt(hir::TyU64)),
-        "isize" => Some(SignedInt(hir::TyIs)),
-        "usize" => Some(UnsignedInt(hir::TyUs)),
-        _ => None
-    }
-}
-
-#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
-pub enum ReprAttr {
-    ReprAny,
-    ReprInt(Span, IntType),
-    ReprExtern,
-    ReprPacked,
-    ReprSimd,
-}
-
-impl ReprAttr {
-    pub fn is_ffi_safe(&self) -> bool {
-        match *self {
-            ReprAny => false,
-            ReprInt(_sp, ity) => ity.is_ffi_safe(),
-            ReprExtern => true,
-            ReprPacked => false,
-            ReprSimd => true,
-        }
-    }
-}
-
-#[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
-pub enum IntType {
-    SignedInt(hir::IntTy),
-    UnsignedInt(hir::UintTy)
-}
-
-impl IntType {
-    #[inline]
-    pub fn is_signed(self) -> bool {
-        match self {
-            SignedInt(..) => true,
-            UnsignedInt(..) => false
-        }
-    }
-    fn is_ffi_safe(self) -> bool {
-        match self {
-            SignedInt(hir::TyI8) | UnsignedInt(hir::TyU8) |
-            SignedInt(hir::TyI16) | UnsignedInt(hir::TyU16) |
-            SignedInt(hir::TyI32) | UnsignedInt(hir::TyU32) |
-            SignedInt(hir::TyI64) | UnsignedInt(hir::TyU64) => true,
-            SignedInt(hir::TyIs) | UnsignedInt(hir::TyUs) => false
-        }
-    }
-}
index ba20b46090afc9aa9e357d15a517cfdd13fafb87..c1bcba1830f6485c61a634b4d6dced03a973ef9f 100644 (file)
@@ -12,7 +12,8 @@
 //! and returns a piece of the same type.
 
 use hir::*;
-use syntax::ast::{Ident, NodeId, DUMMY_NODE_ID};
+use syntax::ast::{Ident, Name, NodeId, DUMMY_NODE_ID, Attribute, Attribute_, MetaItem};
+use syntax::ast::{MetaWord, MetaList, MetaNameValue};
 use hir;
 use syntax::codemap::{respan, Span, Spanned};
 use syntax::owned_slice::OwnedSlice;
@@ -28,7 +29,9 @@ pub trait MoveMap<T> {
 }
 
 impl<T> MoveMap<T> for Vec<T> {
-    fn move_map<F>(mut self, mut f: F) -> Vec<T> where F: FnMut(T) -> T {
+    fn move_map<F>(mut self, mut f: F) -> Vec<T>
+        where F: FnMut(T) -> T
+    {
         for p in &mut self {
             unsafe {
                 // FIXME(#5016) this shouldn't need to zero to be safe.
@@ -40,7 +43,9 @@ impl<T> MoveMap<T> for Vec<T> {
 }
 
 impl<T> MoveMap<T> for OwnedSlice<T> {
-    fn move_map<F>(self, f: F) -> OwnedSlice<T> where F: FnMut(T) -> T {
+    fn move_map<F>(self, f: F) -> OwnedSlice<T>
+        where F: FnMut(T) -> T
+    {
         OwnedSlice::from_vec(self.into_vec().move_map(f))
     }
 }
@@ -146,6 +151,10 @@ pub trait Folder : Sized {
         noop_fold_variant(v, self)
     }
 
+    fn fold_name(&mut self, n: Name) -> Name {
+        noop_fold_name(n, self)
+    }
+
     fn fold_ident(&mut self, i: Ident) -> Ident {
         noop_fold_ident(i, self)
     }
@@ -162,15 +171,15 @@ pub trait Folder : Sized {
         noop_fold_path_parameters(p, self)
     }
 
-    fn fold_angle_bracketed_parameter_data(&mut self, p: AngleBracketedParameterData)
-                                           -> AngleBracketedParameterData
-    {
+    fn fold_angle_bracketed_parameter_data(&mut self,
+                                           p: AngleBracketedParameterData)
+                                           -> AngleBracketedParameterData {
         noop_fold_angle_bracketed_parameter_data(p, self)
     }
 
-    fn fold_parenthesized_parameter_data(&mut self, p: ParenthesizedParameterData)
-                                         -> ParenthesizedParameterData
-    {
+    fn fold_parenthesized_parameter_data(&mut self,
+                                         p: ParenthesizedParameterData)
+                                         -> ParenthesizedParameterData {
         noop_fold_parenthesized_parameter_data(p, self)
     }
 
@@ -214,8 +223,8 @@ pub trait Folder : Sized {
         noop_fold_poly_trait_ref(p, self)
     }
 
-    fn fold_struct_def(&mut self, struct_def: P<StructDef>) -> P<StructDef> {
-        noop_fold_struct_def(struct_def, self)
+    fn fold_variant_data(&mut self, vdata: VariantData) -> VariantData {
+        noop_fold_variant_data(vdata, self)
     }
 
     fn fold_lifetimes(&mut self, lts: Vec<Lifetime>) -> Vec<Lifetime> {
@@ -238,17 +247,13 @@ pub trait Folder : Sized {
         noop_fold_opt_lifetime(o_lt, self)
     }
 
-    fn fold_variant_arg(&mut self, va: VariantArg) -> VariantArg {
-        noop_fold_variant_arg(va, self)
-    }
-
-    fn fold_opt_bounds(&mut self, b: Option<OwnedSlice<TyParamBound>>)
+    fn fold_opt_bounds(&mut self,
+                       b: Option<OwnedSlice<TyParamBound>>)
                        -> Option<OwnedSlice<TyParamBound>> {
         noop_fold_opt_bounds(b, self)
     }
 
-    fn fold_bounds(&mut self, b: OwnedSlice<TyParamBound>)
-                       -> OwnedSlice<TyParamBound> {
+    fn fold_bounds(&mut self, b: OwnedSlice<TyParamBound>) -> OwnedSlice<TyParamBound> {
         noop_fold_bounds(b, self)
     }
 
@@ -264,13 +269,11 @@ pub trait Folder : Sized {
         noop_fold_field(field, self)
     }
 
-    fn fold_where_clause(&mut self, where_clause: WhereClause)
-                         -> WhereClause {
+    fn fold_where_clause(&mut self, where_clause: WhereClause) -> WhereClause {
         noop_fold_where_clause(where_clause, self)
     }
 
-    fn fold_where_predicate(&mut self, where_predicate: WherePredicate)
-                            -> WherePredicate {
+    fn fold_where_predicate(&mut self, where_predicate: WherePredicate) -> WherePredicate {
         noop_fold_where_predicate(where_predicate, self)
     }
 
@@ -283,43 +286,44 @@ pub trait Folder : Sized {
     }
 }
 
-pub fn noop_fold_meta_items<T: Folder>(meta_items: Vec<P<MetaItem>>, fld: &mut T)
+pub fn noop_fold_meta_items<T: Folder>(meta_items: Vec<P<MetaItem>>,
+                                       fld: &mut T)
                                        -> Vec<P<MetaItem>> {
     meta_items.move_map(|x| fld.fold_meta_item(x))
 }
 
 pub fn noop_fold_view_path<T: Folder>(view_path: P<ViewPath>, fld: &mut T) -> P<ViewPath> {
-    view_path.map(|Spanned {node, span}| Spanned {
-        node: match node {
-            ViewPathSimple(ident, path) => {
-                ViewPathSimple(ident, fld.fold_path(path))
-            }
-            ViewPathGlob(path) => {
-                ViewPathGlob(fld.fold_path(path))
-            }
-            ViewPathList(path, path_list_idents) => {
-                ViewPathList(fld.fold_path(path),
-                             path_list_idents.move_map(|path_list_ident| {
-                                Spanned {
-                                    node: match path_list_ident.node {
-                                        PathListIdent { id, name, rename } =>
-                                            PathListIdent {
-                                                id: fld.new_id(id),
-                                                name: name,
-                                                rename: rename,
-                                            },
-                                        PathListMod { id, rename } =>
-                                            PathListMod {
-                                                id: fld.new_id(id),
-                                                rename: rename,
-                                            }
-                                    },
-                                    span: fld.new_span(path_list_ident.span)
-                                }
-                             }))
-            }
-        },
-        span: fld.new_span(span)
+    view_path.map(|Spanned { node, span }| {
+        Spanned {
+            node: match node {
+                ViewPathSimple(name, path) => {
+                    ViewPathSimple(name, fld.fold_path(path))
+                }
+                ViewPathGlob(path) => {
+                    ViewPathGlob(fld.fold_path(path))
+                }
+                ViewPathList(path, path_list_idents) => {
+                    ViewPathList(fld.fold_path(path),
+                                 path_list_idents.move_map(|path_list_ident| {
+                                     Spanned {
+                                         node: match path_list_ident.node {
+                                             PathListIdent { id, name, rename } => PathListIdent {
+                                                 id: fld.new_id(id),
+                                                 name: name,
+                                                 rename: rename,
+                                             },
+                                             PathListMod { id, rename } => PathListMod {
+                                                 id: fld.new_id(id),
+                                                 rename: rename,
+                                             },
+                                         },
+                                         span: fld.new_span(path_list_ident.span),
+                                     }
+                                 }))
+                }
+            },
+            span: fld.new_span(span),
+        }
     })
 }
 
@@ -327,7 +331,7 @@ pub fn fold_attrs<T: Folder>(attrs: Vec<Attribute>, fld: &mut T) -> Vec<Attribut
     attrs.into_iter().flat_map(|x| fld.fold_attribute(x)).collect()
 }
 
-pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm, fld: &mut T) -> Arm {
+pub fn noop_fold_arm<T: Folder>(Arm { attrs, pats, guard, body }: Arm, fld: &mut T) -> Arm {
     Arm {
         attrs: fold_attrs(attrs, fld),
         pats: pats.move_map(|x| fld.fold_pat(x)),
@@ -337,76 +341,89 @@ pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm, fld: &mut T
 }
 
 pub fn noop_fold_decl<T: Folder>(d: P<Decl>, fld: &mut T) -> SmallVector<P<Decl>> {
-    d.and_then(|Spanned {node, span}| match node {
-        DeclLocal(l) => SmallVector::one(P(Spanned {
-            node: DeclLocal(fld.fold_local(l)),
-            span: fld.new_span(span)
-        })),
-        DeclItem(it) => fld.fold_item(it).into_iter().map(|i| P(Spanned {
-            node: DeclItem(i),
-            span: fld.new_span(span)
-        })).collect()
+    d.and_then(|Spanned { node, span }| {
+        match node {
+            DeclLocal(l) => SmallVector::one(P(Spanned {
+                node: DeclLocal(fld.fold_local(l)),
+                span: fld.new_span(span),
+            })),
+            DeclItem(it) => fld.fold_item(it)
+                               .into_iter()
+                               .map(|i| {
+                                   P(Spanned {
+                                       node: DeclItem(i),
+                                       span: fld.new_span(span),
+                                   })
+                               })
+                               .collect(),
+        }
     })
 }
 
 pub fn noop_fold_ty_binding<T: Folder>(b: P<TypeBinding>, fld: &mut T) -> P<TypeBinding> {
-    b.map(|TypeBinding { id, ident, ty, span }| TypeBinding {
-        id: fld.new_id(id),
-        ident: ident,
-        ty: fld.fold_ty(ty),
-        span: fld.new_span(span),
+    b.map(|TypeBinding { id, name, ty, span }| {
+        TypeBinding {
+            id: fld.new_id(id),
+            name: name,
+            ty: fld.fold_ty(ty),
+            span: fld.new_span(span),
+        }
     })
 }
 
 pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
-    t.map(|Ty {id, node, span}| Ty {
-        id: fld.new_id(id),
-        node: match node {
-            TyInfer => node,
-            TyVec(ty) => TyVec(fld.fold_ty(ty)),
-            TyPtr(mt) => TyPtr(fld.fold_mt(mt)),
-            TyRptr(region, mt) => {
-                TyRptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt))
-            }
-            TyBareFn(f) => {
-                TyBareFn(f.map(|BareFnTy {lifetimes, unsafety, abi, decl}| BareFnTy {
-                    lifetimes: fld.fold_lifetime_defs(lifetimes),
-                    unsafety: unsafety,
-                    abi: abi,
-                    decl: fld.fold_fn_decl(decl)
-                }))
-            }
-            TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))),
-            TyParen(ty) => TyParen(fld.fold_ty(ty)),
-            TyPath(qself, path) => {
-                let qself = qself.map(|QSelf { ty, position }| {
-                    QSelf {
-                        ty: fld.fold_ty(ty),
-                        position: position
-                    }
-                });
-                TyPath(qself, fld.fold_path(path))
-            }
-            TyObjectSum(ty, bounds) => {
-                TyObjectSum(fld.fold_ty(ty),
-                            fld.fold_bounds(bounds))
-            }
-            TyFixedLengthVec(ty, e) => {
-                TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
-            }
-            TyTypeof(expr) => {
-                TyTypeof(fld.fold_expr(expr))
-            }
-            TyPolyTraitRef(bounds) => {
-                TyPolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
-            }
-        },
-        span: fld.new_span(span)
+    t.map(|Ty { id, node, span }| {
+        Ty {
+            id: fld.new_id(id),
+            node: match node {
+                TyInfer => node,
+                TyVec(ty) => TyVec(fld.fold_ty(ty)),
+                TyPtr(mt) => TyPtr(fld.fold_mt(mt)),
+                TyRptr(region, mt) => {
+                    TyRptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt))
+                }
+                TyBareFn(f) => {
+                    TyBareFn(f.map(|BareFnTy { lifetimes, unsafety, abi, decl }| {
+                        BareFnTy {
+                            lifetimes: fld.fold_lifetime_defs(lifetimes),
+                            unsafety: unsafety,
+                            abi: abi,
+                            decl: fld.fold_fn_decl(decl),
+                        }
+                    }))
+                }
+                TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))),
+                TyParen(ty) => TyParen(fld.fold_ty(ty)),
+                TyPath(qself, path) => {
+                    let qself = qself.map(|QSelf { ty, position }| {
+                        QSelf {
+                            ty: fld.fold_ty(ty),
+                            position: position,
+                        }
+                    });
+                    TyPath(qself, fld.fold_path(path))
+                }
+                TyObjectSum(ty, bounds) => {
+                    TyObjectSum(fld.fold_ty(ty), fld.fold_bounds(bounds))
+                }
+                TyFixedLengthVec(ty, e) => {
+                    TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
+                }
+                TyTypeof(expr) => {
+                    TyTypeof(fld.fold_expr(expr))
+                }
+                TyPolyTraitRef(bounds) => {
+                    TyPolyTraitRef(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
+                }
+            },
+            span: fld.new_span(span),
+        }
     })
 }
 
-pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, items}: ForeignMod,
-                                        fld: &mut T) -> ForeignMod {
+pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod { abi, items }: ForeignMod,
+                                        fld: &mut T)
+                                        -> ForeignMod {
     ForeignMod {
         abi: abi,
         items: items.move_map(|x| fld.fold_foreign_item(x)),
@@ -414,27 +431,21 @@ pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, items}: ForeignMod,
 }
 
 pub fn noop_fold_variant<T: Folder>(v: P<Variant>, fld: &mut T) -> P<Variant> {
-    v.map(|Spanned {node: Variant_ {id, name, attrs, kind, disr_expr, vis}, span}| Spanned {
+    v.map(|Spanned {node: Variant_ {name, attrs, data, disr_expr}, span}| Spanned {
         node: Variant_ {
-            id: fld.new_id(id),
             name: name,
             attrs: fold_attrs(attrs, fld),
-            kind: match kind {
-                TupleVariantKind(variant_args) => {
-                    TupleVariantKind(variant_args.move_map(|x|
-                        fld.fold_variant_arg(x)))
-                }
-                StructVariantKind(struct_def) => {
-                    StructVariantKind(fld.fold_struct_def(struct_def))
-                }
-            },
+            data: fld.fold_variant_data(data),
             disr_expr: disr_expr.map(|e| fld.fold_expr(e)),
-            vis: vis,
         },
         span: fld.new_span(span),
     })
 }
 
+pub fn noop_fold_name<T: Folder>(n: Name, _: &mut T) -> Name {
+    n
+}
+
 pub fn noop_fold_ident<T: Folder>(i: Ident, _: &mut T) -> Ident {
     i
 }
@@ -443,20 +454,22 @@ pub fn noop_fold_usize<T: Folder>(i: usize, _: &mut T) -> usize {
     i
 }
 
-pub fn noop_fold_path<T: Folder>(Path {global, segments, span}: Path, fld: &mut T) -> Path {
+pub fn noop_fold_path<T: Folder>(Path { global, segments, span }: Path, fld: &mut T) -> Path {
     Path {
         global: global,
-        segments: segments.move_map(|PathSegment {identifier, parameters}| PathSegment {
-            identifier: fld.fold_ident(identifier),
-            parameters: fld.fold_path_parameters(parameters),
+        segments: segments.move_map(|PathSegment { identifier, parameters }| {
+            PathSegment {
+                identifier: fld.fold_ident(identifier),
+                parameters: fld.fold_path_parameters(parameters),
+            }
         }),
-        span: fld.new_span(span)
+        span: fld.new_span(span),
     }
 }
 
-pub fn noop_fold_path_parameters<T: Folder>(path_parameters: PathParameters, fld: &mut T)
-                                            -> PathParameters
-{
+pub fn noop_fold_path_parameters<T: Folder>(path_parameters: PathParameters,
+                                            fld: &mut T)
+                                            -> PathParameters {
     match path_parameters {
         AngleBracketedParameters(data) =>
             AngleBracketedParameters(fld.fold_angle_bracketed_parameter_data(data)),
@@ -467,31 +480,35 @@ pub fn noop_fold_path_parameters<T: Folder>(path_parameters: PathParameters, fld
 
 pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedParameterData,
                                                            fld: &mut T)
-                                                           -> AngleBracketedParameterData
-{
+                                                           -> AngleBracketedParameterData {
     let AngleBracketedParameterData { lifetimes, types, bindings } = data;
-    AngleBracketedParameterData { lifetimes: fld.fold_lifetimes(lifetimes),
-                                  types: types.move_map(|ty| fld.fold_ty(ty)),
-                                  bindings: bindings.move_map(|b| fld.fold_ty_binding(b)) }
+    AngleBracketedParameterData {
+        lifetimes: fld.fold_lifetimes(lifetimes),
+        types: types.move_map(|ty| fld.fold_ty(ty)),
+        bindings: bindings.move_map(|b| fld.fold_ty_binding(b)),
+    }
 }
 
 pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedParameterData,
                                                          fld: &mut T)
-                                                         -> ParenthesizedParameterData
-{
+                                                         -> ParenthesizedParameterData {
     let ParenthesizedParameterData { inputs, output, span } = data;
-    ParenthesizedParameterData { inputs: inputs.move_map(|ty| fld.fold_ty(ty)),
-                                 output: output.map(|ty| fld.fold_ty(ty)),
-                                 span: fld.new_span(span) }
+    ParenthesizedParameterData {
+        inputs: inputs.move_map(|ty| fld.fold_ty(ty)),
+        output: output.map(|ty| fld.fold_ty(ty)),
+        span: fld.new_span(span),
+    }
 }
 
 pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> {
-    l.map(|Local {id, pat, ty, init, span}| Local {
-        id: fld.new_id(id),
-        ty: ty.map(|t| fld.fold_ty(t)),
-        pat: fld.fold_pat(pat),
-        init: init.map(|e| fld.fold_expr(e)),
-        span: fld.new_span(span)
+    l.map(|Local { id, pat, ty, init, span }| {
+        Local {
+            id: fld.new_id(id),
+            ty: ty.map(|t| fld.fold_ty(t)),
+            pat: fld.fold_pat(pat),
+            init: init.map(|e| fld.fold_expr(e)),
+            span: fld.new_span(span),
+        }
     })
 }
 
@@ -502,69 +519,75 @@ pub fn noop_fold_attribute<T: Folder>(at: Attribute, fld: &mut T) -> Option<Attr
             id: id,
             style: style,
             value: fld.fold_meta_item(value),
-            is_sugared_doc: is_sugared_doc
+            is_sugared_doc: is_sugared_doc,
         },
-        span: fld.new_span(span)
+        span: fld.new_span(span),
     })
 }
 
-pub fn noop_fold_explicit_self_underscore<T: Folder>(es: ExplicitSelf_, fld: &mut T)
+pub fn noop_fold_explicit_self_underscore<T: Folder>(es: ExplicitSelf_,
+                                                     fld: &mut T)
                                                      -> ExplicitSelf_ {
     match es {
         SelfStatic | SelfValue(_) => es,
-        SelfRegion(lifetime, m, ident) => {
-            SelfRegion(fld.fold_opt_lifetime(lifetime), m, ident)
+        SelfRegion(lifetime, m, name) => {
+            SelfRegion(fld.fold_opt_lifetime(lifetime), m, name)
         }
-        SelfExplicit(typ, ident) => {
-            SelfExplicit(fld.fold_ty(typ), ident)
+        SelfExplicit(typ, name) => {
+            SelfExplicit(fld.fold_ty(typ), name)
         }
     }
 }
 
-pub fn noop_fold_explicit_self<T: Folder>(Spanned {span, node}: ExplicitSelf, fld: &mut T)
+pub fn noop_fold_explicit_self<T: Folder>(Spanned { span, node }: ExplicitSelf,
+                                          fld: &mut T)
                                           -> ExplicitSelf {
     Spanned {
         node: fld.fold_explicit_self_underscore(node),
-        span: fld.new_span(span)
+        span: fld.new_span(span),
     }
 }
 
 pub fn noop_fold_meta_item<T: Folder>(mi: P<MetaItem>, fld: &mut T) -> P<MetaItem> {
-    mi.map(|Spanned {node, span}| Spanned {
-        node: match node {
-            MetaWord(id) => MetaWord(id),
-            MetaList(id, mis) => {
-                MetaList(id, mis.move_map(|e| fld.fold_meta_item(e)))
-            }
-            MetaNameValue(id, s) => MetaNameValue(id, s)
-        },
-        span: fld.new_span(span)
+    mi.map(|Spanned { node, span }| {
+        Spanned {
+            node: match node {
+                MetaWord(id) => MetaWord(id),
+                MetaList(id, mis) => {
+                    MetaList(id, mis.move_map(|e| fld.fold_meta_item(e)))
+                }
+                MetaNameValue(id, s) => MetaNameValue(id, s),
+            },
+            span: fld.new_span(span),
+        }
     })
 }
 
-pub fn noop_fold_arg<T: Folder>(Arg {id, pat, ty}: Arg, fld: &mut T) -> Arg {
+pub fn noop_fold_arg<T: Folder>(Arg { id, pat, ty }: Arg, fld: &mut T) -> Arg {
     Arg {
         id: fld.new_id(id),
         pat: fld.fold_pat(pat),
-        ty: fld.fold_ty(ty)
+        ty: fld.fold_ty(ty),
     }
 }
 
 pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> {
-    decl.map(|FnDecl {inputs, output, variadic}| FnDecl {
-        inputs: inputs.move_map(|x| fld.fold_arg(x)),
-        output: match output {
-            Return(ty) => Return(fld.fold_ty(ty)),
-            DefaultReturn(span) => DefaultReturn(span),
-            NoReturn(span) => NoReturn(span)
-        },
-        variadic: variadic
+    decl.map(|FnDecl { inputs, output, variadic }| {
+        FnDecl {
+            inputs: inputs.move_map(|x| fld.fold_arg(x)),
+            output: match output {
+                Return(ty) => Return(fld.fold_ty(ty)),
+                DefaultReturn(span) => DefaultReturn(span),
+                NoReturn(span) => NoReturn(span),
+            },
+            variadic: variadic,
+        }
     })
 }
 
-pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
-                                   -> TyParamBound
-                                   where T: Folder {
+pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T) -> TyParamBound
+    where T: Folder
+{
     match tpb {
         TraitTyParamBound(ty, modifier) => TraitTyParamBound(fld.fold_poly_trait_ref(ty), modifier),
         RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)),
@@ -572,17 +595,18 @@ pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
 }
 
 pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
-    let TyParam {id, ident, bounds, default, span} = tp;
+    let TyParam {id, name, bounds, default, span} = tp;
     TyParam {
         id: fld.new_id(id),
-        ident: ident,
+        name: name,
         bounds: fld.fold_bounds(bounds),
         default: default.map(|x| fld.fold_ty(x)),
-        span: span
+        span: span,
     }
 }
 
-pub fn noop_fold_ty_params<T: Folder>(tps: OwnedSlice<TyParam>, fld: &mut T)
+pub fn noop_fold_ty_params<T: Folder>(tps: OwnedSlice<TyParam>,
+                                      fld: &mut T)
                                       -> OwnedSlice<TyParam> {
     tps.move_map(|tp| fld.fold_ty_param(tp))
 }
@@ -591,12 +615,11 @@ pub fn noop_fold_lifetime<T: Folder>(l: Lifetime, fld: &mut T) -> Lifetime {
     Lifetime {
         id: fld.new_id(l.id),
         name: l.name,
-        span: fld.new_span(l.span)
+        span: fld.new_span(l.span),
     }
 }
 
-pub fn noop_fold_lifetime_def<T: Folder>(l: LifetimeDef, fld: &mut T)
-                                         -> LifetimeDef {
+pub fn noop_fold_lifetime_def<T: Folder>(l: LifetimeDef, fld: &mut T) -> LifetimeDef {
     LifetimeDef {
         lifetime: fld.fold_lifetime(l.lifetime),
         bounds: fld.fold_lifetimes(l.bounds),
@@ -607,18 +630,17 @@ pub fn noop_fold_lifetimes<T: Folder>(lts: Vec<Lifetime>, fld: &mut T) -> Vec<Li
     lts.move_map(|l| fld.fold_lifetime(l))
 }
 
-pub fn noop_fold_lifetime_defs<T: Folder>(lts: Vec<LifetimeDef>, fld: &mut T)
-                                          -> Vec<LifetimeDef> {
+pub fn noop_fold_lifetime_defs<T: Folder>(lts: Vec<LifetimeDef>, fld: &mut T) -> Vec<LifetimeDef> {
     lts.move_map(|l| fld.fold_lifetime_def(l))
 }
 
-pub fn noop_fold_opt_lifetime<T: Folder>(o_lt: Option<Lifetime>, fld: &mut T)
-                                         -> Option<Lifetime> {
+pub fn noop_fold_opt_lifetime<T: Folder>(o_lt: Option<Lifetime>, fld: &mut T) -> Option<Lifetime> {
     o_lt.map(|lt| fld.fold_lifetime(lt))
 }
 
-pub fn noop_fold_generics<T: Folder>(Generics {ty_params, lifetimes, where_clause}: Generics,
-                                     fld: &mut T) -> Generics {
+pub fn noop_fold_generics<T: Folder>(Generics { ty_params, lifetimes, where_clause }: Generics,
+                                     fld: &mut T)
+                                     -> Generics {
     Generics {
         ty_params: fld.fold_ty_params(ty_params),
         lifetimes: fld.fold_lifetime_defs(lifetimes),
@@ -626,22 +648,16 @@ pub fn noop_fold_generics<T: Folder>(Generics {ty_params, lifetimes, where_claus
     }
 }
 
-pub fn noop_fold_where_clause<T: Folder>(
-                              WhereClause {id, predicates}: WhereClause,
-                              fld: &mut T)
-                              -> WhereClause {
+pub fn noop_fold_where_clause<T: Folder>(WhereClause { id, predicates }: WhereClause,
+                                         fld: &mut T)
+                                         -> WhereClause {
     WhereClause {
         id: fld.new_id(id),
-        predicates: predicates.move_map(|predicate| {
-            fld.fold_where_predicate(predicate)
-        })
+        predicates: predicates.move_map(|predicate| fld.fold_where_predicate(predicate)),
     }
 }
 
-pub fn noop_fold_where_predicate<T: Folder>(
-                                 pred: WherePredicate,
-                                 fld: &mut T)
-                                 -> WherePredicate {
+pub fn noop_fold_where_predicate<T: Folder>(pred: WherePredicate, fld: &mut T) -> WherePredicate {
     match pred {
         hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate{bound_lifetimes,
                                                                      bounded_ty,
@@ -651,7 +667,7 @@ pub fn noop_fold_where_predicate<T: Folder>(
                 bound_lifetimes: fld.fold_lifetime_defs(bound_lifetimes),
                 bounded_ty: fld.fold_ty(bounded_ty),
                 bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)),
-                span: fld.new_span(span)
+                span: fld.new_span(span),
             })
         }
         hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{lifetime,
@@ -660,28 +676,33 @@ pub fn noop_fold_where_predicate<T: Folder>(
             hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
                 span: fld.new_span(span),
                 lifetime: fld.fold_lifetime(lifetime),
-                bounds: bounds.move_map(|bound| fld.fold_lifetime(bound))
+                bounds: bounds.move_map(|bound| fld.fold_lifetime(bound)),
             })
         }
         hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{id,
                                                                path,
                                                                ty,
                                                                span}) => {
-            hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{
+            hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
                 id: fld.new_id(id),
                 path: fld.fold_path(path),
-                ty:fld.fold_ty(ty),
-                span: fld.new_span(span)
+                ty: fld.fold_ty(ty),
+                span: fld.new_span(span),
             })
         }
     }
 }
 
-pub fn noop_fold_struct_def<T: Folder>(struct_def: P<StructDef>, fld: &mut T) -> P<StructDef> {
-    struct_def.map(|StructDef { fields, ctor_id }| StructDef {
-        fields: fields.move_map(|f| fld.fold_struct_field(f)),
-        ctor_id: ctor_id.map(|cid| fld.new_id(cid)),
-    })
+pub fn noop_fold_variant_data<T: Folder>(vdata: VariantData, fld: &mut T) -> VariantData {
+    match vdata {
+        VariantData::Struct(fields, id) => {
+            VariantData::Struct(fields.move_map(|f| fld.fold_struct_field(f)), fld.new_id(id))
+        }
+        VariantData::Tuple(fields, id) => {
+            VariantData::Tuple(fields.move_map(|f| fld.fold_struct_field(f)), fld.new_id(id))
+        }
+        VariantData::Unit(id) => VariantData::Unit(fld.new_id(id))
+    }
 }
 
 pub fn noop_fold_trait_ref<T: Folder>(p: TraitRef, fld: &mut T) -> TraitRef {
@@ -713,50 +734,45 @@ pub fn noop_fold_struct_field<T: Folder>(f: StructField, fld: &mut T) -> StructF
             ty: fld.fold_ty(ty),
             attrs: fold_attrs(attrs, fld),
         },
-        span: fld.new_span(span)
+        span: fld.new_span(span),
     }
 }
 
-pub fn noop_fold_field<T: Folder>(Field {ident, expr, span}: Field, folder: &mut T) -> Field {
+pub fn noop_fold_field<T: Folder>(Field { name, expr, span }: Field, folder: &mut T) -> Field {
     Field {
-        ident: respan(ident.span, folder.fold_ident(ident.node)),
+        name: respan(folder.new_span(name.span),
+                     folder.fold_name(name.node)),
         expr: folder.fold_expr(expr),
-        span: folder.new_span(span)
+        span: folder.new_span(span),
     }
 }
 
-pub fn noop_fold_mt<T: Folder>(MutTy {ty, mutbl}: MutTy, folder: &mut T) -> MutTy {
+pub fn noop_fold_mt<T: Folder>(MutTy { ty, mutbl }: MutTy, folder: &mut T) -> MutTy {
     MutTy {
         ty: folder.fold_ty(ty),
         mutbl: mutbl,
     }
 }
 
-pub fn noop_fold_opt_bounds<T: Folder>(b: Option<OwnedSlice<TyParamBound>>, folder: &mut T)
+pub fn noop_fold_opt_bounds<T: Folder>(b: Option<OwnedSlice<TyParamBound>>,
+                                       folder: &mut T)
                                        -> Option<OwnedSlice<TyParamBound>> {
     b.map(|bounds| folder.fold_bounds(bounds))
 }
 
-fn noop_fold_bounds<T: Folder>(bounds: TyParamBounds, folder: &mut T)
-                          -> TyParamBounds {
+fn noop_fold_bounds<T: Folder>(bounds: TyParamBounds, folder: &mut T) -> TyParamBounds {
     bounds.move_map(|bound| folder.fold_ty_param_bound(bound))
 }
 
-fn noop_fold_variant_arg<T: Folder>(VariantArg {id, ty}: VariantArg, folder: &mut T)
-                                    -> VariantArg {
-    VariantArg {
-        id: folder.new_id(id),
-        ty: folder.fold_ty(ty)
-    }
-}
-
 pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
-    b.map(|Block {id, stmts, expr, rules, span}| Block {
-        id: folder.new_id(id),
-        stmts: stmts.into_iter().flat_map(|s| folder.fold_stmt(s).into_iter()).collect(),
-        expr: expr.map(|x| folder.fold_expr(x)),
-        rules: rules,
-        span: folder.new_span(span),
+    b.map(|Block { id, stmts, expr, rules, span }| {
+        Block {
+            id: folder.new_id(id),
+            stmts: stmts.into_iter().flat_map(|s| folder.fold_stmt(s).into_iter()).collect(),
+            expr: expr.map(|x| folder.fold_expr(x)),
+            rules: rules,
+            span: folder.new_span(span),
+        }
     })
 }
 
@@ -773,14 +789,12 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
             ItemConst(folder.fold_ty(t), folder.fold_expr(e))
         }
         ItemFn(decl, unsafety, constness, abi, generics, body) => {
-            ItemFn(
-                folder.fold_fn_decl(decl),
-                unsafety,
-                constness,
-                abi,
-                folder.fold_generics(generics),
-                folder.fold_block(body)
-            )
+            ItemFn(folder.fold_fn_decl(decl),
+                   unsafety,
+                   constness,
+                   abi,
+                   folder.fold_generics(generics),
+                   folder.fold_block(body))
         }
         ItemMod(m) => ItemMod(folder.fold_mod(m)),
         ItemForeignMod(nm) => ItemForeignMod(folder.fold_foreign_mod(nm)),
@@ -788,23 +802,25 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
             ItemTy(folder.fold_ty(t), folder.fold_generics(generics))
         }
         ItemEnum(enum_definition, generics) => {
-            ItemEnum(
-                hir::EnumDef {
-                    variants: enum_definition.variants.move_map(|x| folder.fold_variant(x)),
-                },
-                folder.fold_generics(generics))
+            ItemEnum(hir::EnumDef {
+                         variants: enum_definition.variants.move_map(|x| folder.fold_variant(x)),
+                     },
+                     folder.fold_generics(generics))
         }
         ItemStruct(struct_def, generics) => {
-            let struct_def = folder.fold_struct_def(struct_def);
+            let struct_def = folder.fold_variant_data(struct_def);
             ItemStruct(struct_def, folder.fold_generics(generics))
         }
         ItemDefaultImpl(unsafety, ref trait_ref) => {
-            ItemDefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
+            ItemDefaultImpl(unsafety,
+                            folder.fold_trait_ref((*trait_ref).clone()))
         }
         ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => {
-            let new_impl_items = impl_items.into_iter().flat_map(|item| {
-                folder.fold_impl_item(item).into_iter()
-            }).collect();
+            let new_impl_items = impl_items.into_iter()
+                                           .flat_map(|item| {
+                                               folder.fold_impl_item(item).into_iter()
+                                           })
+                                           .collect();
             let ifce = match ifce {
                 None => None,
                 Some(ref trait_ref) => {
@@ -820,81 +836,84 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
         }
         ItemTrait(unsafety, generics, bounds, items) => {
             let bounds = folder.fold_bounds(bounds);
-            let items = items.into_iter().flat_map(|item| {
-                folder.fold_trait_item(item).into_iter()
-            }).collect();
-            ItemTrait(unsafety,
-                      folder.fold_generics(generics),
-                      bounds,
-                      items)
+            let items = items.into_iter()
+                             .flat_map(|item| folder.fold_trait_item(item).into_iter())
+                             .collect();
+            ItemTrait(unsafety, folder.fold_generics(generics), bounds, items)
         }
     }
 }
 
-pub fn noop_fold_trait_item<T: Folder>(i: P<TraitItem>, folder: &mut T)
+pub fn noop_fold_trait_item<T: Folder>(i: P<TraitItem>,
+                                       folder: &mut T)
                                        -> SmallVector<P<TraitItem>> {
-    SmallVector::one(i.map(|TraitItem {id, ident, attrs, node, span}| TraitItem {
-        id: folder.new_id(id),
-        ident: folder.fold_ident(ident),
-        attrs: fold_attrs(attrs, folder),
-        node: match node {
-            ConstTraitItem(ty, default) => {
-                ConstTraitItem(folder.fold_ty(ty),
-                               default.map(|x| folder.fold_expr(x)))
-            }
-            MethodTraitItem(sig, body) => {
-                MethodTraitItem(noop_fold_method_sig(sig, folder),
-                                body.map(|x| folder.fold_block(x)))
-            }
-            TypeTraitItem(bounds, default) => {
-                TypeTraitItem(folder.fold_bounds(bounds),
-                              default.map(|x| folder.fold_ty(x)))
-            }
-        },
-        span: folder.new_span(span)
+    SmallVector::one(i.map(|TraitItem { id, name, attrs, node, span }| {
+        TraitItem {
+            id: folder.new_id(id),
+            name: folder.fold_name(name),
+            attrs: fold_attrs(attrs, folder),
+            node: match node {
+                ConstTraitItem(ty, default) => {
+                    ConstTraitItem(folder.fold_ty(ty),
+                                   default.map(|x| folder.fold_expr(x)))
+                }
+                MethodTraitItem(sig, body) => {
+                    MethodTraitItem(noop_fold_method_sig(sig, folder),
+                                    body.map(|x| folder.fold_block(x)))
+                }
+                TypeTraitItem(bounds, default) => {
+                    TypeTraitItem(folder.fold_bounds(bounds),
+                                  default.map(|x| folder.fold_ty(x)))
+                }
+            },
+            span: folder.new_span(span),
+        }
     }))
 }
 
-pub fn noop_fold_impl_item<T: Folder>(i: P<ImplItem>, folder: &mut T)
-                                      -> SmallVector<P<ImplItem>> {
-    SmallVector::one(i.map(|ImplItem {id, ident, attrs, node, vis, span}| ImplItem {
-        id: folder.new_id(id),
-        ident: folder.fold_ident(ident),
-        attrs: fold_attrs(attrs, folder),
-        vis: vis,
-        node: match node  {
-            ConstImplItem(ty, expr) => {
-                ConstImplItem(folder.fold_ty(ty), folder.fold_expr(expr))
-            }
-            MethodImplItem(sig, body) => {
-                MethodImplItem(noop_fold_method_sig(sig, folder),
-                               folder.fold_block(body))
-            }
-            TypeImplItem(ty) => TypeImplItem(folder.fold_ty(ty)),
-        },
-        span: folder.new_span(span)
+pub fn noop_fold_impl_item<T: Folder>(i: P<ImplItem>, folder: &mut T) -> SmallVector<P<ImplItem>> {
+    SmallVector::one(i.map(|ImplItem { id, name, attrs, node, vis, span }| {
+        ImplItem {
+            id: folder.new_id(id),
+            name: folder.fold_name(name),
+            attrs: fold_attrs(attrs, folder),
+            vis: vis,
+            node: match node {
+                ConstImplItem(ty, expr) => {
+                    ConstImplItem(folder.fold_ty(ty), folder.fold_expr(expr))
+                }
+                MethodImplItem(sig, body) => {
+                    MethodImplItem(noop_fold_method_sig(sig, folder),
+                                   folder.fold_block(body))
+                }
+                TypeImplItem(ty) => TypeImplItem(folder.fold_ty(ty)),
+            },
+            span: folder.new_span(span),
+        }
     }))
 }
 
-pub fn noop_fold_mod<T: Folder>(Mod {inner, items}: Mod, folder: &mut T) -> Mod {
+pub fn noop_fold_mod<T: Folder>(Mod { inner, items }: Mod, folder: &mut T) -> Mod {
     Mod {
         inner: folder.new_span(inner),
         items: items.into_iter().flat_map(|x| folder.fold_item(x).into_iter()).collect(),
     }
 }
 
-pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, config, span, exported_macros}: Crate,
-                                  folder: &mut T) -> Crate {
+pub fn noop_fold_crate<T: Folder>(Crate { module, attrs, config, span, exported_macros }: Crate,
+                                  folder: &mut T)
+                                  -> Crate {
     let config = folder.fold_meta_items(config);
 
     let mut items = folder.fold_item(P(hir::Item {
-        ident: token::special_idents::invalid,
-        attrs: attrs,
-        id: DUMMY_NODE_ID,
-        vis: hir::Public,
-        span: span,
-        node: hir::ItemMod(module),
-    })).into_iter();
+                              name: token::special_idents::invalid.name,
+                              attrs: attrs,
+                              id: DUMMY_NODE_ID,
+                              vis: hir::Public,
+                              span: span,
+                              node: hir::ItemMod(module),
+                          }))
+                          .into_iter();
 
     let (module, attrs, span) = match items.next() {
         Some(item) => {
@@ -910,7 +929,9 @@ pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, config, span, exported_m
         None => (hir::Mod {
             inner: span,
             items: vec![],
-        }, vec![], span)
+        },
+                 vec![],
+                 span),
     };
 
     Crate {
@@ -928,8 +949,9 @@ pub fn noop_fold_item<T: Folder>(i: P<Item>, folder: &mut T) -> SmallVector<P<It
 }
 
 // fold one item into exactly one item
-pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span}: Item,
-                                        folder: &mut T) -> Item {
+pub fn noop_fold_item_simple<T: Folder>(Item { id, name, attrs, node, vis, span }: Item,
+                                        folder: &mut T)
+                                        -> Item {
     let id = folder.new_id(id);
     let node = folder.fold_item_underscore(node);
     // FIXME: we should update the impl_pretty_name, but it uses pretty printing.
@@ -943,29 +965,32 @@ pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span}
 
     Item {
         id: id,
-        ident: folder.fold_ident(ident),
+        name: folder.fold_name(name),
         attrs: fold_attrs(attrs, folder),
         node: node,
         vis: vis,
-        span: folder.new_span(span)
+        span: folder.new_span(span),
     }
 }
 
 pub fn noop_fold_foreign_item<T: Folder>(ni: P<ForeignItem>, folder: &mut T) -> P<ForeignItem> {
-    ni.map(|ForeignItem {id, ident, attrs, node, span, vis}| ForeignItem {
-        id: folder.new_id(id),
-        ident: folder.fold_ident(ident),
-        attrs: fold_attrs(attrs, folder),
-        node: match node {
-            ForeignItemFn(fdec, generics) => {
-                ForeignItemFn(folder.fold_fn_decl(fdec), folder.fold_generics(generics))
-            }
-            ForeignItemStatic(t, m) => {
-                ForeignItemStatic(folder.fold_ty(t), m)
-            }
-        },
-        vis: vis,
-        span: folder.new_span(span)
+    ni.map(|ForeignItem { id, name, attrs, node, span, vis }| {
+        ForeignItem {
+            id: folder.new_id(id),
+            name: folder.fold_name(name),
+            attrs: fold_attrs(attrs, folder),
+            node: match node {
+                ForeignItemFn(fdec, generics) => {
+                    ForeignItemFn(folder.fold_fn_decl(fdec),
+                                  folder.fold_generics(generics))
+                }
+                ForeignItemStatic(t, m) => {
+                    ForeignItemStatic(folder.fold_ty(t), m)
+                }
+            },
+            vis: vis,
+            span: folder.new_span(span),
+        }
     })
 }
 
@@ -976,64 +1001,70 @@ pub fn noop_fold_method_sig<T: Folder>(sig: MethodSig, folder: &mut T) -> Method
         explicit_self: folder.fold_explicit_self(sig.explicit_self),
         unsafety: sig.unsafety,
         constness: sig.constness,
-        decl: folder.fold_fn_decl(sig.decl)
+        decl: folder.fold_fn_decl(sig.decl),
     }
 }
 
 pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
-    p.map(|Pat {id, node, span}| Pat {
-        id: folder.new_id(id),
-        node: match node {
-            PatWild(k) => PatWild(k),
-            PatIdent(binding_mode, pth1, sub) => {
-                PatIdent(binding_mode,
-                        Spanned{span: folder.new_span(pth1.span),
-                                node: folder.fold_ident(pth1.node)},
-                        sub.map(|x| folder.fold_pat(x)))
-            }
-            PatLit(e) => PatLit(folder.fold_expr(e)),
-            PatEnum(pth, pats) => {
-                PatEnum(folder.fold_path(pth),
-                        pats.map(|pats| pats.move_map(|x| folder.fold_pat(x))))
-            }
-            PatQPath(qself, pth) => {
-                let qself = QSelf {ty: folder.fold_ty(qself.ty), .. qself};
-                PatQPath(qself, folder.fold_path(pth))
-            }
-            PatStruct(pth, fields, etc) => {
-                let pth = folder.fold_path(pth);
-                let fs = fields.move_map(|f| {
-                    Spanned { span: folder.new_span(f.span),
-                              node: hir::FieldPat {
-                                  ident: f.node.ident,
-                                  pat: folder.fold_pat(f.node.pat),
-                                  is_shorthand: f.node.is_shorthand,
-                              }}
-                });
-                PatStruct(pth, fs, etc)
-            }
-            PatTup(elts) => PatTup(elts.move_map(|x| folder.fold_pat(x))),
-            PatBox(inner) => PatBox(folder.fold_pat(inner)),
-            PatRegion(inner, mutbl) => PatRegion(folder.fold_pat(inner), mutbl),
-            PatRange(e1, e2) => {
-                PatRange(folder.fold_expr(e1), folder.fold_expr(e2))
+    p.map(|Pat { id, node, span }| {
+        Pat {
+            id: folder.new_id(id),
+            node: match node {
+                PatWild(k) => PatWild(k),
+                PatIdent(binding_mode, pth1, sub) => {
+                    PatIdent(binding_mode,
+                             Spanned {
+                                 span: folder.new_span(pth1.span),
+                                 node: folder.fold_ident(pth1.node),
+                             },
+                             sub.map(|x| folder.fold_pat(x)))
+                }
+                PatLit(e) => PatLit(folder.fold_expr(e)),
+                PatEnum(pth, pats) => {
+                    PatEnum(folder.fold_path(pth),
+                            pats.map(|pats| pats.move_map(|x| folder.fold_pat(x))))
+                }
+                PatQPath(qself, pth) => {
+                    let qself = QSelf { ty: folder.fold_ty(qself.ty), ..qself };
+                    PatQPath(qself, folder.fold_path(pth))
+                }
+                PatStruct(pth, fields, etc) => {
+                    let pth = folder.fold_path(pth);
+                    let fs = fields.move_map(|f| {
+                        Spanned {
+                            span: folder.new_span(f.span),
+                            node: hir::FieldPat {
+                                name: f.node.name,
+                                pat: folder.fold_pat(f.node.pat),
+                                is_shorthand: f.node.is_shorthand,
+                            },
+                        }
+                    });
+                    PatStruct(pth, fs, etc)
+                }
+                PatTup(elts) => PatTup(elts.move_map(|x| folder.fold_pat(x))),
+                PatBox(inner) => PatBox(folder.fold_pat(inner)),
+                PatRegion(inner, mutbl) => PatRegion(folder.fold_pat(inner), mutbl),
+                PatRange(e1, e2) => {
+                    PatRange(folder.fold_expr(e1), folder.fold_expr(e2))
+                }
+                PatVec(before, slice, after) => {
+                    PatVec(before.move_map(|x| folder.fold_pat(x)),
+                           slice.map(|x| folder.fold_pat(x)),
+                           after.move_map(|x| folder.fold_pat(x)))
+                }
             },
-            PatVec(before, slice, after) => {
-                PatVec(before.move_map(|x| folder.fold_pat(x)),
-                       slice.map(|x| folder.fold_pat(x)),
-                       after.move_map(|x| folder.fold_pat(x)))
-            }
-        },
-        span: folder.new_span(span)
+            span: folder.new_span(span),
+        }
     })
 }
 
-pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) -> Expr {
+pub fn noop_fold_expr<T: Folder>(Expr { id, node, span }: Expr, folder: &mut T) -> Expr {
     Expr {
         id: folder.new_id(id),
         node: match node {
-            ExprBox(p, e) => {
-                ExprBox(p.map(|e|folder.fold_expr(e)), folder.fold_expr(e))
+            ExprBox(e) => {
+                ExprBox(folder.fold_expr(e))
             }
             ExprVec(exprs) => {
                 ExprVec(exprs.move_map(|x| folder.fold_expr(x)))
@@ -1046,16 +1077,14 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
                 ExprCall(folder.fold_expr(f),
                          args.move_map(|x| folder.fold_expr(x)))
             }
-            ExprMethodCall(i, tps, args) => {
-                ExprMethodCall(
-                    respan(folder.new_span(i.span), folder.fold_ident(i.node)),
-                    tps.move_map(|x| folder.fold_ty(x)),
-                    args.move_map(|x| folder.fold_expr(x)))
+            ExprMethodCall(name, tps, args) => {
+                ExprMethodCall(respan(folder.new_span(name.span),
+                                      folder.fold_name(name.node)),
+                               tps.move_map(|x| folder.fold_ty(x)),
+                               args.move_map(|x| folder.fold_expr(x)))
             }
             ExprBinary(binop, lhs, rhs) => {
-                ExprBinary(binop,
-                        folder.fold_expr(lhs),
-                        folder.fold_expr(rhs))
+                ExprBinary(binop, folder.fold_expr(lhs), folder.fold_expr(rhs))
             }
             ExprUnary(binop, ohs) => {
                 ExprUnary(binop, folder.fold_expr(ohs))
@@ -1077,12 +1106,12 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
             }
             ExprLoop(body, opt_ident) => {
                 ExprLoop(folder.fold_block(body),
-                        opt_ident.map(|i| folder.fold_ident(i)))
+                         opt_ident.map(|i| folder.fold_ident(i)))
             }
             ExprMatch(expr, arms, source) => {
                 ExprMatch(folder.fold_expr(expr),
-                        arms.move_map(|x| folder.fold_arm(x)),
-                        source)
+                          arms.move_map(|x| folder.fold_arm(x)),
+                          source)
             }
             ExprClosure(capture_clause, decl, body) => {
                 ExprClosure(capture_clause,
@@ -1094,19 +1123,17 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
                 ExprAssign(folder.fold_expr(el), folder.fold_expr(er))
             }
             ExprAssignOp(op, el, er) => {
-                ExprAssignOp(op,
-                            folder.fold_expr(el),
-                            folder.fold_expr(er))
+                ExprAssignOp(op, folder.fold_expr(el), folder.fold_expr(er))
             }
-            ExprField(el, ident) => {
+            ExprField(el, name) => {
                 ExprField(folder.fold_expr(el),
-                          respan(folder.new_span(ident.span),
-                                 folder.fold_ident(ident.node)))
+                          respan(folder.new_span(name.span),
+                                 folder.fold_name(name.node)))
             }
-            ExprTupField(el, ident) => {
+            ExprTupField(el, index) => {
                 ExprTupField(folder.fold_expr(el),
-                             respan(folder.new_span(ident.span),
-                                    folder.fold_usize(ident.node)))
+                             respan(folder.new_span(index.span),
+                                    folder.fold_usize(index.node)))
             }
             ExprIndex(el, er) => {
                 ExprIndex(folder.fold_expr(el), folder.fold_expr(er))
@@ -1119,19 +1146,19 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
                 let qself = qself.map(|QSelf { ty, position }| {
                     QSelf {
                         ty: folder.fold_ty(ty),
-                        position: position
+                        position: position,
                     }
                 });
                 ExprPath(qself, folder.fold_path(path))
             }
-            ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|label|
+            ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|label| {
                 respan(folder.new_span(label.span),
-                       folder.fold_ident(label.node)))
-            ),
-            ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|label|
+                       folder.fold_ident(label.node))
+            })),
+            ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|label| {
                 respan(folder.new_span(label.span),
-                       folder.fold_ident(label.node)))
-            ),
+                       folder.fold_ident(label.node))
+            })),
             ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))),
             ExprInlineAsm(InlineAsm {
                 inputs,
@@ -1144,12 +1171,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
                 dialect,
                 expn_id,
             }) => ExprInlineAsm(InlineAsm {
-                inputs: inputs.move_map(|(c, input)| {
-                    (c, folder.fold_expr(input))
-                }),
-                outputs: outputs.move_map(|(c, out, is_rw)| {
-                    (c, folder.fold_expr(out), is_rw)
-                }),
+                inputs: inputs.move_map(|(c, input)| (c, folder.fold_expr(input))),
+                outputs: outputs.move_map(|(c, out, is_rw)| (c, folder.fold_expr(out), is_rw)),
                 asm: asm,
                 asm_str_style: asm_str_style,
                 clobbers: clobbers,
@@ -1160,38 +1183,43 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
             }),
             ExprStruct(path, fields, maybe_expr) => {
                 ExprStruct(folder.fold_path(path),
-                        fields.move_map(|x| folder.fold_field(x)),
-                        maybe_expr.map(|x| folder.fold_expr(x)))
-            },
-            ExprParen(ex) => ExprParen(folder.fold_expr(ex))
+                           fields.move_map(|x| folder.fold_field(x)),
+                           maybe_expr.map(|x| folder.fold_expr(x)))
+            }
         },
-        span: folder.new_span(span)
+        span: folder.new_span(span),
     }
 }
 
-pub fn noop_fold_stmt<T: Folder>(Spanned {node, span}: Stmt, folder: &mut T)
+pub fn noop_fold_stmt<T: Folder>(Spanned { node, span }: Stmt,
+                                 folder: &mut T)
                                  -> SmallVector<P<Stmt>> {
     let span = folder.new_span(span);
     match node {
         StmtDecl(d, id) => {
             let id = folder.new_id(id);
-            folder.fold_decl(d).into_iter().map(|d| P(Spanned {
-                node: StmtDecl(d, id),
-                span: span
-            })).collect()
+            folder.fold_decl(d)
+                  .into_iter()
+                  .map(|d| {
+                      P(Spanned {
+                          node: StmtDecl(d, id),
+                          span: span,
+                      })
+                  })
+                  .collect()
         }
         StmtExpr(e, id) => {
             let id = folder.new_id(id);
             SmallVector::one(P(Spanned {
                 node: StmtExpr(folder.fold_expr(e), id),
-                span: span
+                span: span,
             }))
         }
         StmtSemi(e, id) => {
             let id = folder.new_id(id);
             SmallVector::one(P(Spanned {
                 node: StmtSemi(folder.fold_expr(e), id),
-                span: span
+                span: span,
             }))
         }
     }
index f8f17617310b7b4ef2beef790a21fa224cb66a33..079bf677c8ea6e984532d4e5b764ba0e23a89844 100644 (file)
@@ -10,8 +10,6 @@
 
 // The Rust HIR.
 
-pub use self::AsmDialect::*;
-pub use self::AttrStyle::*;
 pub use self::BindingMode::*;
 pub use self::BinOp_::*;
 pub use self::BlockCheckMode::*;
@@ -19,38 +17,30 @@ pub use self::CaptureClause::*;
 pub use self::Decl_::*;
 pub use self::ExplicitSelf_::*;
 pub use self::Expr_::*;
-pub use self::FloatTy::*;
 pub use self::FunctionRetTy::*;
 pub use self::ForeignItem_::*;
 pub use self::ImplItem_::*;
-pub use self::IntTy::*;
 pub use self::Item_::*;
-pub use self::Lit_::*;
-pub use self::LitIntType::*;
-pub use self::MetaItem_::*;
 pub use self::Mutability::*;
 pub use self::Pat_::*;
 pub use self::PathListItem_::*;
 pub use self::PatWildKind::*;
 pub use self::PrimTy::*;
-pub use self::Sign::*;
 pub use self::Stmt_::*;
-pub use self::StrStyle::*;
 pub use self::StructFieldKind::*;
 pub use self::TraitItem_::*;
 pub use self::Ty_::*;
 pub use self::TyParamBound::*;
-pub use self::UintTy::*;
 pub use self::UnOp::*;
 pub use self::UnsafeSource::*;
-pub use self::VariantKind::*;
 pub use self::ViewPath_::*;
 pub use self::Visibility::*;
 pub use self::PathParameters::*;
 
 use syntax::codemap::{self, Span, Spanned, DUMMY_SP, ExpnId};
 use syntax::abi::Abi;
-use syntax::ast::{Name, Ident, NodeId, DUMMY_NODE_ID, TokenTree};
+use syntax::ast::{Name, Ident, NodeId, DUMMY_NODE_ID, TokenTree, AsmDialect};
+use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, CrateConfig};
 use syntax::owned_slice::OwnedSlice;
 use syntax::parse::token::InternedString;
 use syntax::ptr::P;
@@ -59,23 +49,21 @@ use print::pprust;
 use util;
 
 use std::fmt;
-use std::rc::Rc;
 use serialize::{Encodable, Encoder, Decoder};
 
-
-/// Function name (not all functions have names)
-pub type FnIdent = Option<Ident>;
-
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
 pub struct Lifetime {
     pub id: NodeId,
     pub span: Span,
-    pub name: Name
+    pub name: Name,
 }
 
 impl fmt::Debug for Lifetime {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "lifetime({}: {})", self.id, pprust::lifetime_to_string(self))
+        write!(f,
+               "lifetime({}: {})",
+               self.id,
+               pprust::lifetime_to_string(self))
     }
 }
 
@@ -83,7 +71,7 @@ impl fmt::Debug for Lifetime {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct LifetimeDef {
     pub lifetime: Lifetime,
-    pub bounds: Vec<Lifetime>
+    pub bounds: Vec<Lifetime>,
 }
 
 /// A "Path" is essentially Rust's notion of a name; for instance:
@@ -175,7 +163,8 @@ impl PathParameters {
                 data.types.iter().collect()
             }
             ParenthesizedParameters(ref data) => {
-                data.inputs.iter()
+                data.inputs
+                    .iter()
                     .chain(data.output.iter())
                     .collect()
             }
@@ -243,7 +232,7 @@ pub struct ParenthesizedParameterData {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum TyParamBound {
     TraitTyParamBound(PolyTraitRef, TraitBoundModifier),
-    RegionTyParamBound(Lifetime)
+    RegionTyParamBound(Lifetime),
 }
 
 /// A modifier on a bound, currently this is only used for `?Sized`, where the
@@ -258,11 +247,11 @@ pub type TyParamBounds = OwnedSlice<TyParamBound>;
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct TyParam {
-    pub ident: Ident,
+    pub name: Name,
     pub id: NodeId,
     pub bounds: TyParamBounds,
     pub default: Option<P<Ty>>,
-    pub span: Span
+    pub span: Span,
 }
 
 /// Represents lifetimes and type parameters attached to a declaration
@@ -301,7 +290,7 @@ pub enum WherePredicate {
     /// A lifetime predicate, e.g. `'a: 'b+'c`
     RegionPredicate(WhereRegionPredicate),
     /// An equality predicate (unsupported)
-    EqPredicate(WhereEqPredicate)
+    EqPredicate(WhereEqPredicate),
 }
 
 /// A type bound, eg `for<'c> Foo: Send+Clone+'c`
@@ -333,10 +322,6 @@ pub struct WhereEqPredicate {
     pub ty: P<Ty>,
 }
 
-/// The set of MetaItems that define the compilation environment of the crate,
-/// used to drive conditional compilation
-pub type CrateConfig = Vec<P<MetaItem>> ;
-
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct Crate {
     pub module: Mod,
@@ -351,51 +336,17 @@ pub struct Crate {
 /// Not parsed directly, but created on macro import or `macro_rules!` expansion.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct MacroDef {
-    pub ident: Ident,
+    pub name: Name,
     pub attrs: Vec<Attribute>,
     pub id: NodeId,
     pub span: Span,
-    pub imported_from: Option<Ident>,
+    pub imported_from: Option<Name>,
     pub export: bool,
     pub use_locally: bool,
     pub allow_internal_unstable: bool,
     pub body: Vec<TokenTree>,
 }
 
-pub type MetaItem = Spanned<MetaItem_>;
-
-#[derive(Clone, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum MetaItem_ {
-    MetaWord(InternedString),
-    MetaList(InternedString, Vec<P<MetaItem>>),
-    MetaNameValue(InternedString, Lit),
-}
-
-// can't be derived because the MetaList requires an unordered comparison
-impl PartialEq for MetaItem_ {
-    fn eq(&self, other: &MetaItem_) -> bool {
-        match *self {
-            MetaWord(ref ns) => match *other {
-                MetaWord(ref no) => (*ns) == (*no),
-                _ => false
-            },
-            MetaNameValue(ref ns, ref vs) => match *other {
-                MetaNameValue(ref no, ref vo) => {
-                    (*ns) == (*no) && vs.node == vo.node
-                }
-                _ => false
-            },
-            MetaList(ref ns, ref miss) => match *other {
-                MetaList(ref no, ref miso) => {
-                    ns == no &&
-                        miss.iter().all(|mi| miso.iter().any(|x| x.node == mi.node))
-                }
-                _ => false
-            }
-        }
-    }
-}
-
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct Block {
     /// Statements in a block
@@ -430,7 +381,7 @@ impl fmt::Debug for Pat {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct FieldPat {
     /// The identifier for the field
-    pub ident: Ident,
+    pub name: Name,
     /// The pattern the field is destructured to
     pub pat: P<Pat>,
     pub is_shorthand: bool,
@@ -464,7 +415,7 @@ pub enum Pat_ {
     /// which it is. The resolver determines this, and
     /// records this pattern's NodeId in an auxiliary
     /// set (of "PatIdents that refer to nullary enums")
-    PatIdent(BindingMode, SpannedIdent, Option<P<Pat>>),
+    PatIdent(BindingMode, Spanned<Ident>, Option<P<Pat>>),
 
     /// "None" means a * pattern where we don't bind the fields to names.
     PatEnum(Path, Option<Vec<P<Pat>>>),
@@ -543,14 +494,12 @@ pub type BinOp = Spanned<BinOp_>;
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum UnOp {
-    /// The `box` operator
-    UnUniq,
     /// The `*` operator for dereferencing
     UnDeref,
     /// The `!` operator for logical inversion
     UnNot,
     /// The `-` operator for negation
-    UnNeg
+    UnNeg,
 }
 
 /// A statement
@@ -560,7 +509,8 @@ impl fmt::Debug for Stmt_ {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         // Sadness.
         let spanned = codemap::dummy_spanned(self.clone());
-        write!(f, "stmt({}: {})",
+        write!(f,
+               "stmt({}: {})",
                util::stmt_id(&spanned),
                pprust::stmt_to_string(&spanned))
     }
@@ -612,19 +562,20 @@ pub struct Arm {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct Field {
-    pub ident: SpannedIdent,
+    pub name: Spanned<Name>,
     pub expr: P<Expr>,
     pub span: Span,
 }
 
-pub type SpannedIdent = Spanned<Ident>;
-
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum BlockCheckMode {
     DefaultBlock,
     UnsafeBlock(UnsafeSource),
     PushUnsafeBlock(UnsafeSource),
     PopUnsafeBlock(UnsafeSource),
+    // Within this block (but outside a PopUnstableBlock), we suspend checking of stability.
+    PushUnstableBlock,
+    PopUnstableBlock,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
@@ -634,7 +585,7 @@ pub enum UnsafeSource {
 }
 
 /// An expression
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash,)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
 pub struct Expr {
     pub id: NodeId,
     pub node: Expr_,
@@ -649,8 +600,8 @@ impl fmt::Debug for Expr {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Expr_ {
-    /// First expr is the place; second expr is the value.
-    ExprBox(Option<P<Expr>>, P<Expr>),
+    /// A `box x` expression.
+    ExprBox(P<Expr>),
     /// An array (`[a, b, c, d]`)
     ExprVec(Vec<P<Expr>>),
     /// A function call
@@ -660,7 +611,7 @@ pub enum Expr_ {
     ExprCall(P<Expr>, Vec<P<Expr>>),
     /// A method call (`x.foo::<Bar, Baz>(a, b, c, d)`)
     ///
-    /// The `SpannedIdent` is the identifier for the method name.
+    /// The `Spanned<Name>` is the identifier for the method name.
     /// The vector of `Ty`s are the ascripted type parameters for the method
     /// (within the angle brackets).
     ///
@@ -670,7 +621,7 @@ pub enum Expr_ {
     ///
     /// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
     /// `ExprMethodCall(foo, [Bar, Baz], [x, a, b, c, d])`.
-    ExprMethodCall(SpannedIdent, Vec<P<Ty>>, Vec<P<Expr>>),
+    ExprMethodCall(Spanned<Name>, Vec<P<Ty>>, Vec<P<Expr>>),
     /// A tuple (`(a, b, c ,d)`)
     ExprTup(Vec<P<Expr>>),
     /// A binary operation (For example: `a + b`, `a * b`)
@@ -685,7 +636,6 @@ pub enum Expr_ {
     ///
     /// `if expr { block } else { expr }`
     ExprIf(P<Expr>, P<Block>, Option<P<Expr>>),
-    // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
     /// A while loop, with an optional label
     ///
     /// `'label: while expr { block }`
@@ -693,7 +643,6 @@ pub enum Expr_ {
     /// Conditionless loop (can be exited with break, continue, or return)
     ///
     /// `'label: loop { block }`
-    // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
     ExprLoop(P<Block>, Option<Ident>),
     /// A `match` block, with a source that indicates whether or not it is
     /// the result of a desugaring, and if so, which kind.
@@ -710,7 +659,7 @@ pub enum Expr_ {
     /// For example, `a += 1`.
     ExprAssignOp(BinOp, P<Expr>, P<Expr>),
     /// Access of a named struct field (`obj.foo`)
-    ExprField(P<Expr>, SpannedIdent),
+    ExprField(P<Expr>, Spanned<Name>),
     /// Access of an unnamed field of a struct or tuple-struct
     ///
     /// For example, `foo.0`.
@@ -730,9 +679,9 @@ pub enum Expr_ {
     /// A referencing operation (`&a` or `&mut a`)
     ExprAddrOf(Mutability, P<Expr>),
     /// A `break`, with an optional label to break
-    ExprBreak(Option<SpannedIdent>),
+    ExprBreak(Option<Spanned<Ident>>),
     /// A `continue`, with an optional label
-    ExprAgain(Option<SpannedIdent>),
+    ExprAgain(Option<Spanned<Ident>>),
     /// A `return`, with an optional value to be returned
     ExprRet(Option<P<Expr>>),
 
@@ -750,9 +699,6 @@ pub enum Expr_ {
     /// For example, `[1u8; 5]`. The first expression is the element
     /// to be repeated; the second is the number of times to repeat it.
     ExprRepeat(P<Expr>, P<Expr>),
-
-    /// No-op: used solely so we can pretty-print faithfully
-    ExprParen(P<Expr>)
 }
 
 /// The explicit Self type in a "qualified path". The actual
@@ -770,13 +716,15 @@ pub enum Expr_ {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct QSelf {
     pub ty: P<Ty>,
-    pub position: usize
+    pub position: usize,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum MatchSource {
     Normal,
-    IfLetDesugar { contains_else_clause: bool },
+    IfLetDesugar {
+        contains_else_clause: bool,
+    },
     WhileLetDesugar,
     ForLoopDesugar,
 }
@@ -787,72 +735,6 @@ pub enum CaptureClause {
     CaptureByRef,
 }
 
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
-pub enum StrStyle {
-    /// A regular string, like `"foo"`
-    CookedStr,
-    /// A raw string, like `r##"foo"##`
-    ///
-    /// The uint is the number of `#` symbols used
-    RawStr(usize)
-}
-
-/// A literal
-pub type Lit = Spanned<Lit_>;
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
-pub enum Sign {
-    Minus,
-    Plus
-}
-
-impl Sign {
-    pub fn new<T: IntSign>(n: T) -> Sign {
-        n.sign()
-    }
-}
-
-pub trait IntSign {
-    fn sign(&self) -> Sign;
-}
-macro_rules! doit {
-    ($($t:ident)*) => ($(impl IntSign for $t {
-        #[allow(unused_comparisons)]
-        fn sign(&self) -> Sign {
-            if *self < 0 {Minus} else {Plus}
-        }
-    })*)
-}
-doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
-pub enum LitIntType {
-    SignedIntLit(IntTy, Sign),
-    UnsignedIntLit(UintTy),
-    UnsuffixedIntLit(Sign)
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum Lit_ {
-    /// A string literal (`"foo"`)
-    LitStr(InternedString, StrStyle),
-    /// A byte string (`b"foo"`)
-    LitByteStr(Rc<Vec<u8>>),
-    /// A byte char (`b'f'`)
-    LitByte(u8),
-    /// A character literal (`'a'`)
-    LitChar(char),
-    /// An integer literal (`1u8`)
-    LitInt(u64, LitIntType),
-    /// A float literal (`1f64` or `1E10f64`)
-    LitFloat(InternedString, FloatTy),
-    /// A float literal without a suffix (`1.0 or 1.0E10`)
-    LitFloatUnsuffixed(InternedString),
-    /// A boolean literal
-    LitBool(bool),
-}
-
 // NB: If you change this, you'll probably want to change the corresponding
 // type structure in middle/ty.rs as well.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@ -861,13 +743,6 @@ pub struct MutTy {
     pub mutbl: Mutability,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct TypeField {
-    pub ident: Ident,
-    pub mt: MutTy,
-    pub span: Span,
-}
-
 /// Represents a method's signature in a trait declaration,
 /// or in an implementation.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@ -887,7 +762,7 @@ pub struct MethodSig {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct TraitItem {
     pub id: NodeId,
-    pub ident: Ident,
+    pub name: Name,
     pub attrs: Vec<Attribute>,
     pub node: TraitItem_,
     pub span: Span,
@@ -903,7 +778,7 @@ pub enum TraitItem_ {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct ImplItem {
     pub id: NodeId,
-    pub ident: Ident,
+    pub name: Name,
     pub vis: Visibility,
     pub attrs: Vec<Attribute>,
     pub node: ImplItem_,
@@ -917,104 +792,11 @@ pub enum ImplItem_ {
     TypeImplItem(P<Ty>),
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
-pub enum IntTy {
-    TyIs,
-    TyI8,
-    TyI16,
-    TyI32,
-    TyI64,
-}
-
-impl fmt::Debug for IntTy {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(self, f)
-    }
-}
-
-impl fmt::Display for IntTy {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", util::int_ty_to_string(*self, None))
-    }
-}
-
-impl IntTy {
-    pub fn bit_width(&self) -> Option<usize> {
-        Some(match *self {
-            TyIs => return None,
-            TyI8 => 8,
-            TyI16 => 16,
-            TyI32 => 32,
-            TyI64 => 64,
-        })
-    }
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
-pub enum UintTy {
-    TyUs,
-    TyU8,
-    TyU16,
-    TyU32,
-    TyU64,
-}
-
-impl UintTy {
-    pub fn bit_width(&self) -> Option<usize> {
-        Some(match *self {
-            TyUs => return None,
-            TyU8 => 8,
-            TyU16 => 16,
-            TyU32 => 32,
-            TyU64 => 64,
-        })
-    }
-}
-
-impl fmt::Debug for UintTy {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(self, f)
-    }
-}
-
-impl fmt::Display for UintTy {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", util::uint_ty_to_string(*self, None))
-    }
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
-pub enum FloatTy {
-    TyF32,
-    TyF64,
-}
-
-impl fmt::Debug for FloatTy {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(self, f)
-    }
-}
-
-impl fmt::Display for FloatTy {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}", util::float_ty_to_string(*self))
-    }
-}
-
-impl FloatTy {
-    pub fn bit_width(&self) -> usize {
-        match *self {
-            TyF32 => 32,
-            TyF64 => 64,
-        }
-    }
-}
-
 // Bind a type to an associated type: `A=Foo`.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct TypeBinding {
     pub id: NodeId,
-    pub ident: Ident,
+    pub name: Name,
     pub ty: P<Ty>,
     pub span: Span,
 }
@@ -1042,7 +824,7 @@ pub enum PrimTy {
     TyFloat(FloatTy),
     TyStr,
     TyBool,
-    TyChar
+    TyChar,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@ -1050,7 +832,7 @@ pub struct BareFnTy {
     pub unsafety: Unsafety,
     pub abi: Abi,
     pub lifetimes: Vec<LifetimeDef>,
-    pub decl: P<FnDecl>
+    pub decl: P<FnDecl>,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@ -1066,7 +848,7 @@ pub enum Ty_ {
     /// A bare function (e.g. `fn(usize) -> bool`)
     TyBareFn(P<BareFnTy>),
     /// A tuple (`(A, B, C, D,...)`)
-    TyTup(Vec<P<Ty>> ),
+    TyTup(Vec<P<Ty>>),
     /// A path (`module::module::...::Type`), optionally
     /// "qualified", e.g. `<Vec<T> as SomeTrait>::SomeType`.
     ///
@@ -1085,12 +867,6 @@ pub enum Ty_ {
     TyInfer,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
-pub enum AsmDialect {
-    AsmAtt,
-    AsmIntel
-}
-
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct InlineAsm {
     pub asm: InternedString,
@@ -1114,7 +890,10 @@ pub struct Arg {
 
 impl Arg {
     pub fn new_self(span: Span, mutability: Mutability, self_ident: Ident) -> Arg {
-        let path = Spanned{span:span,node:self_ident};
+        let path = Spanned {
+            span: span,
+            node: self_ident,
+        };
         Arg {
             // HACK(eddyb) fake type for the self argument.
             ty: P(Ty {
@@ -1125,9 +904,9 @@ impl Arg {
             pat: P(Pat {
                 id: DUMMY_NODE_ID,
                 node: PatIdent(BindByValue(mutability), path, None),
-                span: span
+                span: span,
             }),
-            id: DUMMY_NODE_ID
+            id: DUMMY_NODE_ID,
         }
     }
 }
@@ -1137,7 +916,7 @@ impl Arg {
 pub struct FnDecl {
     pub inputs: Vec<Arg>,
     pub output: FunctionRetTy,
-    pub variadic: bool
+    pub variadic: bool,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@ -1155,9 +934,10 @@ pub enum Constness {
 impl fmt::Display for Unsafety {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt(match *self {
-            Unsafety::Normal => "normal",
-            Unsafety::Unsafe => "unsafe",
-        }, f)
+                              Unsafety::Normal => "normal",
+                              Unsafety::Unsafe => "unsafe",
+                          },
+                          f)
     }
 }
 
@@ -1199,7 +979,7 @@ impl FunctionRetTy {
         match *self {
             NoReturn(span) => span,
             DefaultReturn(span) => span,
-            Return(ref ty) => ty.span
+            Return(ref ty) => ty.span,
         }
     }
 }
@@ -1210,11 +990,11 @@ pub enum ExplicitSelf_ {
     /// No self
     SelfStatic,
     /// `self`
-    SelfValue(Ident),
+    SelfValue(Name),
     /// `&'lt self`, `&'lt mut self`
-    SelfRegion(Option<Lifetime>, Mutability, Ident),
+    SelfRegion(Option<Lifetime>, Mutability, Name),
     /// `self: TYPE`
-    SelfExplicit(P<Ty>, Ident),
+    SelfExplicit(P<Ty>, Name),
 }
 
 pub type ExplicitSelf = Spanned<ExplicitSelf_>;
@@ -1234,20 +1014,6 @@ pub struct ForeignMod {
     pub items: Vec<P<ForeignItem>>,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct VariantArg {
-    pub ty: P<Ty>,
-    pub id: NodeId,
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum VariantKind {
-    /// Tuple variant, e.g. `Foo(A, B)`
-    TupleVariantKind(Vec<VariantArg>),
-    /// Struct variant, e.g. `Foo {x: A, y: B}`
-    StructVariantKind(P<StructDef>),
-}
-
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct EnumDef {
     pub variants: Vec<P<Variant>>,
@@ -1255,13 +1021,11 @@ pub struct EnumDef {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct Variant_ {
-    pub name: Ident,
+    pub name: Name,
     pub attrs: Vec<Attribute>,
-    pub kind: VariantKind,
-    pub id: NodeId,
+    pub data: VariantData,
     /// Explicit discriminant, eg `Foo = 1`
     pub disr_expr: Option<P<Expr>>,
-    pub vis: Visibility,
 }
 
 pub type Variant = Spanned<Variant_>;
@@ -1269,28 +1033,35 @@ pub type Variant = Spanned<Variant_>;
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum PathListItem_ {
     PathListIdent {
-        name: Ident,
+        name: Name,
         /// renamed in list, eg `use foo::{bar as baz};`
-        rename: Option<Ident>,
-        id: NodeId
+        rename: Option<Name>,
+        id: NodeId,
     },
     PathListMod {
         /// renamed in list, eg `use foo::{self as baz};`
-        rename: Option<Ident>,
-        id: NodeId
-    }
+        rename: Option<Name>,
+        id: NodeId,
+    },
 }
 
 impl PathListItem_ {
     pub fn id(&self) -> NodeId {
         match *self {
-            PathListIdent { id, .. } | PathListMod { id, .. } => id
+            PathListIdent { id, .. } | PathListMod { id, .. } => id,
+        }
+    }
+
+    pub fn name(&self) -> Option<Name> {
+        match *self {
+            PathListIdent { name, .. } => Some(name),
+            PathListMod { .. } => None,
         }
     }
 
-    pub fn rename(&self) -> Option<Ident> {
+    pub fn rename(&self) -> Option<Name> {
         match *self {
-            PathListIdent { rename, .. } | PathListMod { rename, .. } => rename
+            PathListIdent { rename, .. } | PathListMod { rename, .. } => rename,
         }
     }
 }
@@ -1307,37 +1078,13 @@ pub enum ViewPath_ {
     /// or just
     ///
     /// `foo::bar::baz` (with `as baz` implicitly on the right)
-    ViewPathSimple(Ident, Path),
+    ViewPathSimple(Name, Path),
 
     /// `foo::bar::*`
     ViewPathGlob(Path),
 
     /// `foo::bar::{a,b,c}`
-    ViewPathList(Path, Vec<PathListItem>)
-}
-
-/// Meta-data associated with an item
-pub type Attribute = Spanned<Attribute_>;
-
-/// Distinguishes between Attributes that decorate items and Attributes that
-/// are contained as statements within items. These two cases need to be
-/// distinguished for pretty-printing.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
-pub enum AttrStyle {
-    AttrOuter,
-    AttrInner,
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
-pub struct AttrId(pub usize);
-
-/// Doc-comments are promoted to attributes that have is_sugared_doc = true
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct Attribute_ {
-    pub id: AttrId,
-    pub style: AttrStyle,
-    pub value: P<MetaItem>,
-    pub is_sugared_doc: bool,
+    ViewPathList(Path, Vec<PathListItem>),
 }
 
 /// TraitRef's appear in impls.
@@ -1373,7 +1120,7 @@ impl Visibility {
     pub fn inherit_from(&self, parent_visibility: Visibility) -> Visibility {
         match self {
             &Inherited => parent_visibility,
-            &Public => *self
+            &Public => *self,
         }
     }
 }
@@ -1387,10 +1134,10 @@ pub struct StructField_ {
 }
 
 impl StructField_ {
-    pub fn ident(&self) -> Option<Ident> {
+    pub fn name(&self) -> Option<Name> {
         match self.kind {
-            NamedField(ref ident, _) => Some(ident.clone()),
-            UnnamedField(_) => None
+            NamedField(name, _) => Some(name),
+            UnnamedField(_) => None,
         }
     }
 }
@@ -1399,7 +1146,7 @@ pub type StructField = Spanned<StructField_>;
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum StructFieldKind {
-    NamedField(Ident, Visibility),
+    NamedField(Name, Visibility),
     /// Element of a tuple-like struct
     UnnamedField(Visibility),
 }
@@ -1413,13 +1160,45 @@ impl StructFieldKind {
     }
 }
 
+/// Fields and Ids of enum variants and structs
+///
+/// For enum variants: `NodeId` represents both an Id of the variant itself (relevant for all
+/// variant kinds) and an Id of the variant's constructor (not relevant for `Struct`-variants).
+/// One shared Id can be successfully used for these two purposes.
+/// Id of the whole enum lives in `Item`.
+///
+/// For structs: `NodeId` represents an Id of the structure's constructor, so it is not actually
+/// used for `Struct`-structs (but still presents). Structures don't have an analogue of "Id of
+/// the variant itself" from enum variants.
+/// Id of the whole struct lives in `Item`.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct StructDef {
-    /// Fields, not including ctor
-    pub fields: Vec<StructField>,
-    /// ID of the constructor. This is only used for tuple- or enum-like
-    /// structs.
-    pub ctor_id: Option<NodeId>,
+pub enum VariantData {
+    Struct(Vec<StructField>, NodeId),
+    Tuple(Vec<StructField>, NodeId),
+    Unit(NodeId),
+}
+
+impl VariantData {
+    pub fn fields(&self) -> &[StructField] {
+        match *self {
+            VariantData::Struct(ref fields, _) | VariantData::Tuple(ref fields, _) => fields,
+            _ => &[],
+        }
+    }
+    pub fn id(&self) -> NodeId {
+        match *self {
+            VariantData::Struct(_, id) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id
+        }
+    }
+    pub fn is_struct(&self) -> bool {
+        if let VariantData::Struct(..) = *self { true } else { false }
+    }
+    pub fn is_tuple(&self) -> bool {
+        if let VariantData::Tuple(..) = *self { true } else { false }
+    }
+    pub fn is_unit(&self) -> bool {
+        if let VariantData::Unit(..) = *self { true } else { false }
+    }
 }
 
 /*
@@ -1431,7 +1210,7 @@ pub struct StructDef {
 /// The name might be a dummy name in case of anonymous items
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct Item {
-    pub ident: Ident,
+    pub name: Name,
     pub attrs: Vec<Attribute>,
     pub id: NodeId,
     pub node: Item_,
@@ -1463,12 +1242,9 @@ pub enum Item_ {
     /// An enum definition, e.g. `enum Foo<A, B> {C<A>, D<B>}`
     ItemEnum(EnumDef, Generics),
     /// A struct definition, e.g. `struct Foo<A> {x: A}`
-    ItemStruct(P<StructDef>, Generics),
+    ItemStruct(VariantData, Generics),
     /// Represents a Trait Declaration
-    ItemTrait(Unsafety,
-              Generics,
-              TyParamBounds,
-              Vec<P<TraitItem>>),
+    ItemTrait(Unsafety, Generics, TyParamBounds, Vec<P<TraitItem>>),
 
     // Default trait implementations
     ///
@@ -1498,14 +1274,14 @@ impl Item_ {
             ItemStruct(..) => "struct",
             ItemTrait(..) => "trait",
             ItemImpl(..) |
-            ItemDefaultImpl(..) => "item"
+            ItemDefaultImpl(..) => "item",
         }
     }
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct ForeignItem {
-    pub ident: Ident,
+    pub name: Name,
     pub attrs: Vec<Attribute>,
     pub node: ForeignItem_,
     pub id: NodeId,
@@ -1527,7 +1303,7 @@ impl ForeignItem_ {
     pub fn descriptive_variant(&self) -> &str {
         match *self {
             ForeignItemFn(..) => "foreign function",
-            ForeignItemStatic(..) => "foreign static item"
+            ForeignItemStatic(..) => "foreign static item",
         }
     }
 }
index fae4f15725534333e423ee3b17606ef92a8fb381..022744cbc3a14e430ff010ae1c60a8660739e208 100644 (file)
 #![feature(staged_api)]
 #![feature(str_char)]
 #![feature(filling_drop)]
-#![feature(str_escape)]
-#![cfg_attr(test, feature(test))]
 
 extern crate serialize;
-#[macro_use] extern crate log;
-#[macro_use] extern crate syntax;
-#[macro_use] #[no_link] extern crate rustc_bitflags;
+#[macro_use]
+extern crate log;
+#[macro_use]
+extern crate syntax;
+#[macro_use]
+#[no_link]
+extern crate rustc_bitflags;
 
 extern crate serialize as rustc_serialize; // used by deriving
 
@@ -50,7 +52,6 @@ pub mod hir;
 pub mod lowering;
 pub mod fold;
 pub mod visit;
-pub mod attr;
 pub mod util;
 
 pub mod print {
index aa7545d52d11e1eb6805a14d397e87c239b1c1c9..42b84b392f37525b4009a115a79f29da113c22b2 100644 (file)
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Lowers the AST to the HIR
+// Lowers the AST to the HIR.
+//
+// Since the AST and HIR are fairly similar, this is mostly a simple procedure,
+// much like a fold. Where lowering involves a bit more work things get more
+// interesting and there are some invariants you should know about. These mostly
+// concern spans and ids.
+//
+// Spans are assigned to AST nodes during parsing and then are modified during
+// expansion to indicate the origin of a node and the process it went through
+// being expanded. Ids are assigned to AST nodes just before lowering.
+//
+// For the simpler lowering steps, ids and spans should be preserved. Unlike
+// expansion we do not preserve the process of lowering in the spans, so spans
+// should not be modified here. When creating a new node (as opposed to
+// 'folding' an existing one), then you create a new id using `next_id()`.
+//
+// You must ensure that ids are unique. That means that you should only use the
+// id from an AST node in a single HIR node (you can assume that AST node ids
+// are unique). Every new node must have a unique id. Avoid cloning HIR nodes.
+// If you do, you must then set the new node's id to a fresh one.
+//
+// Lowering must be reproducable (the compiler only lowers once, but tools and
+// custom lints may lower an AST node to a HIR node to interact with the
+// compiler). The most interesting bit of this is ids - if you lower an AST node
+// and create new HIR nodes with fresh ids, when re-lowering the same node, you
+// must ensure you get the same ids! To do this, we keep track of the next id
+// when we translate a node which requires new ids. By checking this cache and
+// using node ids starting with the cached id, we ensure ids are reproducible.
+// To use this system, you just need to hold on to a CachedIdSetter object
+// whilst lowering. This is an RAII object that takes care of setting and
+// restoring the cached id, etc.
+//
+// This whole system relies on node ids being incremented one at a time and
+// all increments being for lowering. This means that you should not call any
+// non-lowering function which will use new node ids.
+//
+// We must also cache gensym'ed Idents to ensure that we get the same Ident
+// every time we lower a node with gensym'ed names. One consequence of this is
+// that you can only gensym a name once in a lowering (you don't need to worry
+// about nested lowering though). That's because we cache based on the name and
+// the currently cached node id, which is unique per lowered node.
+//
+// Spans are used for error messages and for tools to map semantics back to
+// source code. It is therefore not as important with spans as ids to be strict
+// about use (you can't break the compiler by screwing up a span). Obviously, a
+// HIR node can only have a single span. But multiple nodes can have the same
+// span and spans don't need to be kept in order, etc. Where code is preserved
+// by lowering, it should have the same span as in the AST. Where HIR nodes are
+// new it is probably best to give a span for the whole AST node being lowered.
+// All nodes should have real spans, don't use dummy spans. Tools are likely to
+// get confused if the spans from leaf AST nodes occur in multiple places
+// in the HIR, especially for multiple identifiers.
 
 use hir;
 
+use std::collections::HashMap;
+
 use syntax::ast::*;
 use syntax::ptr::P;
-use syntax::codemap::Spanned;
+use syntax::codemap::{respan, Spanned, Span};
 use syntax::owned_slice::OwnedSlice;
+use syntax::parse::token::{self, str_to_ident};
+use syntax::std_inject;
+
+use std::cell::{Cell, RefCell};
+
+pub struct LoweringContext<'a> {
+    crate_root: Option<&'static str>,
+    // Map AST ids to ids used for expanded nodes.
+    id_cache: RefCell<HashMap<NodeId, NodeId>>,
+    // Use if there are no cached ids for the current node.
+    id_assigner: &'a NodeIdAssigner,
+    // 0 == no cached id. Must be incremented to align with previous id
+    // incrementing.
+    cached_id: Cell<u32>,
+    // Keep track of gensym'ed idents.
+    gensym_cache: RefCell<HashMap<(NodeId, &'static str), Ident>>,
+    // A copy of cached_id, but is also set to an id while it is being cached.
+    gensym_key: Cell<u32>,
+}
+
+impl<'a, 'hir> LoweringContext<'a> {
+    pub fn new(id_assigner: &'a NodeIdAssigner, c: Option<&Crate>) -> LoweringContext<'a> {
+        let crate_root = c.and_then(|c| {
+            if std_inject::no_core(c) {
+                None
+            } else if std_inject::no_std(c) {
+                Some("core")
+            } else {
+                Some("std")
+            }
+        });
+
+        LoweringContext {
+            crate_root: crate_root,
+            id_cache: RefCell::new(HashMap::new()),
+            id_assigner: id_assigner,
+            cached_id: Cell::new(0),
+            gensym_cache: RefCell::new(HashMap::new()),
+            gensym_key: Cell::new(0),
+        }
+    }
 
+    fn next_id(&self) -> NodeId {
+        let cached = self.cached_id.get();
+        if cached == 0 {
+            return self.id_assigner.next_node_id()
+        }
 
-pub fn lower_meta_items(meta_items: &Vec<P<MetaItem>>) -> Vec<P<hir::MetaItem>> {
-    meta_items.iter().map(|x| lower_meta_item(x)).collect()
+        self.cached_id.set(cached + 1);
+        cached
+    }
+
+    fn str_to_ident(&self, s: &'static str) -> Ident {
+        let cached_id = self.gensym_key.get();
+        if cached_id == 0 {
+            return token::gensym_ident(s);
+        }
+
+        let cached = self.gensym_cache.borrow().contains_key(&(cached_id, s));
+        if cached {
+            self.gensym_cache.borrow()[&(cached_id, s)]
+        } else {
+            let result = token::gensym_ident(s);
+            self.gensym_cache.borrow_mut().insert((cached_id, s), result);
+            result
+        }
+    }
 }
 
-pub fn lower_view_path(view_path: &ViewPath) -> P<hir::ViewPath> {
+pub fn lower_view_path(_lctx: &LoweringContext, view_path: &ViewPath) -> P<hir::ViewPath> {
     P(Spanned {
         node: match view_path.node {
             ViewPathSimple(ident, ref path) => {
-                hir::ViewPathSimple(ident, lower_path(path))
+                hir::ViewPathSimple(ident.name, lower_path(_lctx, path))
             }
             ViewPathGlob(ref path) => {
-                hir::ViewPathGlob(lower_path(path))
+                hir::ViewPathGlob(lower_path(_lctx, path))
             }
             ViewPathList(ref path, ref path_list_idents) => {
-                hir::ViewPathList(lower_path(path),
-                             path_list_idents.iter().map(|path_list_ident| {
-                                Spanned {
-                                    node: match path_list_ident.node {
-                                        PathListIdent { id, name, rename } =>
-                                            hir::PathListIdent {
-                                                id: id,
-                                                name: name,
-                                                rename: rename.clone(),
-                                            },
-                                        PathListMod { id, rename } =>
-                                            hir::PathListMod { id: id, rename: rename.clone() }
-                                    },
-                                    span: path_list_ident.span
-                                }
-                             }).collect())
+                hir::ViewPathList(lower_path(_lctx, path),
+                                  path_list_idents.iter()
+                                                  .map(|path_list_ident| {
+                                                      Spanned {
+                                                          node: match path_list_ident.node {
+                                                              PathListIdent { id, name, rename } =>
+                                                                  hir::PathListIdent {
+                                                                  id: id,
+                                                                  name: name.name,
+                                                                  rename: rename.map(|x| x.name),
+                                                              },
+                                                              PathListMod { id, rename } =>
+                                                                  hir::PathListMod {
+                                                                  id: id,
+                                                                  rename: rename.map(|x| x.name),
+                                                              },
+                                                          },
+                                                          span: path_list_ident.span,
+                                                      }
+                                                  })
+                                                  .collect())
             }
         },
         span: view_path.span,
     })
 }
 
-pub fn lower_attrs(attrs: &Vec<Attribute>) -> Vec<hir::Attribute> {
-    attrs.iter().map(|x| lower_attribute(x)).collect()
-}
-
-pub fn lower_arm(arm: &Arm) -> hir::Arm {
+pub fn lower_arm(_lctx: &LoweringContext, arm: &Arm) -> hir::Arm {
     hir::Arm {
-        attrs: lower_attrs(&arm.attrs),
-        pats: arm.pats.iter().map(|x| lower_pat(x)).collect(),
-        guard: arm.guard.as_ref().map(|ref x| lower_expr(x)),
-        body: lower_expr(&arm.body),
+        attrs: arm.attrs.clone(),
+        pats: arm.pats.iter().map(|x| lower_pat(_lctx, x)).collect(),
+        guard: arm.guard.as_ref().map(|ref x| lower_expr(_lctx, x)),
+        body: lower_expr(_lctx, &arm.body),
     }
 }
 
-pub fn lower_decl(d: &Decl) -> P<hir::Decl> {
+pub fn lower_decl(_lctx: &LoweringContext, d: &Decl) -> P<hir::Decl> {
     match d.node {
         DeclLocal(ref l) => P(Spanned {
-            node: hir::DeclLocal(lower_local(l)),
-            span: d.span
+            node: hir::DeclLocal(lower_local(_lctx, l)),
+            span: d.span,
         }),
         DeclItem(ref it) => P(Spanned {
-            node: hir::DeclItem(lower_item(it)),
-            span: d.span
+            node: hir::DeclItem(lower_item(_lctx, it)),
+            span: d.span,
         }),
     }
 }
 
-pub fn lower_ty_binding(b: &TypeBinding) -> P<hir::TypeBinding> {
-    P(hir::TypeBinding { id: b.id, ident: b.ident, ty: lower_ty(&b.ty), span: b.span })
+pub fn lower_ty_binding(_lctx: &LoweringContext, b: &TypeBinding) -> P<hir::TypeBinding> {
+    P(hir::TypeBinding {
+        id: b.id,
+        name: b.ident.name,
+        ty: lower_ty(_lctx, &b.ty),
+        span: b.span,
+    })
 }
 
-pub fn lower_ty(t: &Ty) -> P<hir::Ty> {
+pub fn lower_ty(_lctx: &LoweringContext, t: &Ty) -> P<hir::Ty> {
     P(hir::Ty {
         id: t.id,
         node: match t.node {
             TyInfer => hir::TyInfer,
-            TyVec(ref ty) => hir::TyVec(lower_ty(ty)),
-            TyPtr(ref mt) => hir::TyPtr(lower_mt(mt)),
+            TyVec(ref ty) => hir::TyVec(lower_ty(_lctx, ty)),
+            TyPtr(ref mt) => hir::TyPtr(lower_mt(_lctx, mt)),
             TyRptr(ref region, ref mt) => {
-                hir::TyRptr(lower_opt_lifetime(region), lower_mt(mt))
+                hir::TyRptr(lower_opt_lifetime(_lctx, region),
+                            lower_mt(_lctx, mt))
             }
             TyBareFn(ref f) => {
                 hir::TyBareFn(P(hir::BareFnTy {
-                    lifetimes: lower_lifetime_defs(&f.lifetimes),
-                    unsafety: lower_unsafety(f.unsafety),
+                    lifetimes: lower_lifetime_defs(_lctx, &f.lifetimes),
+                    unsafety: lower_unsafety(_lctx, f.unsafety),
                     abi: f.abi,
-                    decl: lower_fn_decl(&f.decl)
+                    decl: lower_fn_decl(_lctx, &f.decl),
                 }))
             }
-            TyTup(ref tys) => hir::TyTup(tys.iter().map(|ty| lower_ty(ty)).collect()),
-            TyParen(ref ty) => hir::TyParen(lower_ty(ty)),
+            TyTup(ref tys) => hir::TyTup(tys.iter().map(|ty| lower_ty(_lctx, ty)).collect()),
+            TyParen(ref ty) => hir::TyParen(lower_ty(_lctx, ty)),
             TyPath(ref qself, ref path) => {
                 let qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
                     hir::QSelf {
-                        ty: lower_ty(ty),
-                        position: position
+                        ty: lower_ty(_lctx, ty),
+                        position: position,
                     }
                 });
-                hir::TyPath(qself, lower_path(path))
+                hir::TyPath(qself, lower_path(_lctx, path))
             }
             TyObjectSum(ref ty, ref bounds) => {
-                hir::TyObjectSum(lower_ty(ty),
-                            lower_bounds(bounds))
+                hir::TyObjectSum(lower_ty(_lctx, ty), lower_bounds(_lctx, bounds))
             }
             TyFixedLengthVec(ref ty, ref e) => {
-                hir::TyFixedLengthVec(lower_ty(ty), lower_expr(e))
+                hir::TyFixedLengthVec(lower_ty(_lctx, ty), lower_expr(_lctx, e))
             }
             TyTypeof(ref expr) => {
-                hir::TyTypeof(lower_expr(expr))
+                hir::TyTypeof(lower_expr(_lctx, expr))
             }
             TyPolyTraitRef(ref bounds) => {
-                hir::TyPolyTraitRef(bounds.iter().map(|b| lower_ty_param_bound(b)).collect())
+                hir::TyPolyTraitRef(bounds.iter().map(|b| lower_ty_param_bound(_lctx, b)).collect())
             }
             TyMac(_) => panic!("TyMac should have been expanded by now."),
         },
@@ -132,248 +254,225 @@ pub fn lower_ty(t: &Ty) -> P<hir::Ty> {
     })
 }
 
-pub fn lower_foreign_mod(fm: &ForeignMod) -> hir::ForeignMod {
+pub fn lower_foreign_mod(_lctx: &LoweringContext, fm: &ForeignMod) -> hir::ForeignMod {
     hir::ForeignMod {
         abi: fm.abi,
-        items: fm.items.iter().map(|x| lower_foreign_item(x)).collect(),
+        items: fm.items.iter().map(|x| lower_foreign_item(_lctx, x)).collect(),
     }
 }
 
-pub fn lower_variant(v: &Variant) -> P<hir::Variant> {
+pub fn lower_variant(_lctx: &LoweringContext, v: &Variant) -> P<hir::Variant> {
     P(Spanned {
         node: hir::Variant_ {
-            id: v.node.id,
-            name: v.node.name,
-            attrs: lower_attrs(&v.node.attrs),
-            kind: match v.node.kind {
-                TupleVariantKind(ref variant_args) => {
-                    hir::TupleVariantKind(variant_args.iter().map(|ref x|
-                        lower_variant_arg(x)).collect())
-                }
-                StructVariantKind(ref struct_def) => {
-                    hir::StructVariantKind(lower_struct_def(struct_def))
-                }
-            },
-            disr_expr: v.node.disr_expr.as_ref().map(|e| lower_expr(e)),
-            vis: lower_visibility(v.node.vis),
+            name: v.node.name.name,
+            attrs: v.node.attrs.clone(),
+            data: lower_variant_data(_lctx, &v.node.data),
+            disr_expr: v.node.disr_expr.as_ref().map(|e| lower_expr(_lctx, e)),
         },
         span: v.span,
     })
 }
 
-pub fn lower_path(p: &Path) -> hir::Path {
+pub fn lower_path(_lctx: &LoweringContext, p: &Path) -> hir::Path {
     hir::Path {
         global: p.global,
-        segments: p.segments.iter().map(|&PathSegment {identifier, ref parameters}|
-            hir::PathSegment {
-                identifier: identifier,
-                parameters: lower_path_parameters(parameters),
-            }).collect(),
+        segments: p.segments
+                   .iter()
+                   .map(|&PathSegment { identifier, ref parameters }| {
+                       hir::PathSegment {
+                           identifier: identifier,
+                           parameters: lower_path_parameters(_lctx, parameters),
+                       }
+                   })
+                   .collect(),
         span: p.span,
     }
 }
 
-pub fn lower_path_parameters(path_parameters: &PathParameters) -> hir::PathParameters {
+pub fn lower_path_parameters(_lctx: &LoweringContext,
+                             path_parameters: &PathParameters)
+                             -> hir::PathParameters {
     match *path_parameters {
         AngleBracketedParameters(ref data) =>
-            hir::AngleBracketedParameters(lower_angle_bracketed_parameter_data(data)),
+            hir::AngleBracketedParameters(lower_angle_bracketed_parameter_data(_lctx, data)),
         ParenthesizedParameters(ref data) =>
-            hir::ParenthesizedParameters(lower_parenthesized_parameter_data(data)),
+            hir::ParenthesizedParameters(lower_parenthesized_parameter_data(_lctx, data)),
     }
 }
 
-pub fn lower_angle_bracketed_parameter_data(data: &AngleBracketedParameterData)
+pub fn lower_angle_bracketed_parameter_data(_lctx: &LoweringContext,
+                                            data: &AngleBracketedParameterData)
                                             -> hir::AngleBracketedParameterData {
     let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings } = data;
     hir::AngleBracketedParameterData {
-        lifetimes: lower_lifetimes(lifetimes),
-        types: types.iter().map(|ty| lower_ty(ty)).collect(),
-        bindings: bindings.iter().map(|b| lower_ty_binding(b)).collect(),
+        lifetimes: lower_lifetimes(_lctx, lifetimes),
+        types: types.iter().map(|ty| lower_ty(_lctx, ty)).collect(),
+        bindings: bindings.iter().map(|b| lower_ty_binding(_lctx, b)).collect(),
     }
 }
 
-pub fn lower_parenthesized_parameter_data(data: &ParenthesizedParameterData)
+pub fn lower_parenthesized_parameter_data(_lctx: &LoweringContext,
+                                          data: &ParenthesizedParameterData)
                                           -> hir::ParenthesizedParameterData {
     let &ParenthesizedParameterData { ref inputs, ref output, span } = data;
     hir::ParenthesizedParameterData {
-        inputs: inputs.iter().map(|ty| lower_ty(ty)).collect(),
-        output: output.as_ref().map(|ty| lower_ty(ty)),
+        inputs: inputs.iter().map(|ty| lower_ty(_lctx, ty)).collect(),
+        output: output.as_ref().map(|ty| lower_ty(_lctx, ty)),
         span: span,
     }
 }
 
-pub fn lower_local(l: &Local) -> P<hir::Local> {
+pub fn lower_local(_lctx: &LoweringContext, l: &Local) -> P<hir::Local> {
     P(hir::Local {
-            id: l.id,
-            ty: l.ty.as_ref().map(|t| lower_ty(t)),
-            pat: lower_pat(&l.pat),
-            init: l.init.as_ref().map(|e| lower_expr(e)),
-            span: l.span,
-        })
-}
-
-pub fn lower_attribute(at: &Attribute) -> hir::Attribute {
-    Spanned {
-        node: hir::Attribute_ {
-            id: hir::AttrId(at.node.id.0),
-            style: lower_attr_style(at.node.style),
-            value: lower_meta_item(&at.node.value),
-            is_sugared_doc: at.node.is_sugared_doc,
-        },
-        span: at.span,
-    }
-}
-
-// FIXME we should probably just unify hir and ast Attributes.
-pub fn unlower_attribute(at: &hir::Attribute) -> Attribute {
-    Spanned {
-        node: Attribute_ {
-            id: AttrId(at.node.id.0),
-            style: unlower_attr_style(at.node.style),
-            value: unlower_meta_item(&at.node.value),
-            is_sugared_doc: at.node.is_sugared_doc,
-        },
-        span: at.span,
-    }
+        id: l.id,
+        ty: l.ty.as_ref().map(|t| lower_ty(_lctx, t)),
+        pat: lower_pat(_lctx, &l.pat),
+        init: l.init.as_ref().map(|e| lower_expr(_lctx, e)),
+        span: l.span,
+    })
 }
 
-pub fn lower_explicit_self_underscore(es: &ExplicitSelf_) -> hir::ExplicitSelf_ {
+pub fn lower_explicit_self_underscore(_lctx: &LoweringContext,
+                                      es: &ExplicitSelf_)
+                                      -> hir::ExplicitSelf_ {
     match *es {
         SelfStatic => hir::SelfStatic,
-        SelfValue(v) => hir::SelfValue(v),
+        SelfValue(v) => hir::SelfValue(v.name),
         SelfRegion(ref lifetime, m, ident) => {
-            hir::SelfRegion(lower_opt_lifetime(lifetime), lower_mutability(m), ident)
+            hir::SelfRegion(lower_opt_lifetime(_lctx, lifetime),
+                            lower_mutability(_lctx, m),
+                            ident.name)
         }
         SelfExplicit(ref typ, ident) => {
-            hir::SelfExplicit(lower_ty(typ), ident)
+            hir::SelfExplicit(lower_ty(_lctx, typ), ident.name)
         }
     }
 }
 
-pub fn lower_mutability(m: Mutability) -> hir::Mutability {
+pub fn lower_mutability(_lctx: &LoweringContext, m: Mutability) -> hir::Mutability {
     match m {
         MutMutable => hir::MutMutable,
         MutImmutable => hir::MutImmutable,
     }
 }
 
-pub fn lower_explicit_self(s: &ExplicitSelf) -> hir::ExplicitSelf {
-    Spanned { node: lower_explicit_self_underscore(&s.node), span: s.span }
-}
-
-
-pub fn lower_meta_item(mi: &MetaItem) -> P<hir::MetaItem> {
-    P(Spanned {
-        node: match mi.node {
-            MetaWord(ref id) => hir::MetaWord(id.clone()),
-            MetaList(ref id, ref mis) => {
-                hir::MetaList(id.clone(), mis.iter().map(|mi| lower_meta_item(mi)).collect())
-            }
-            MetaNameValue(ref id, ref s) => hir::MetaNameValue(id.clone(), lower_lit(s))
-        },
-        span: mi.span,
-    })
-}
-
-pub fn unlower_meta_item(mi: &hir::MetaItem) -> P<MetaItem> {
-    P(Spanned {
-        node: match mi.node {
-            hir::MetaWord(ref id) => MetaWord(id.clone()),
-            hir::MetaList(ref id, ref mis) => {
-                MetaList(id.clone(), mis.iter().map(|mi| unlower_meta_item(mi)).collect())
-            }
-            hir::MetaNameValue(ref id, ref s) => MetaNameValue(id.clone(), unlower_lit(s))
-        },
-        span: mi.span,
-    })
+pub fn lower_explicit_self(_lctx: &LoweringContext, s: &ExplicitSelf) -> hir::ExplicitSelf {
+    Spanned {
+        node: lower_explicit_self_underscore(_lctx, &s.node),
+        span: s.span,
+    }
 }
 
-pub fn lower_arg(arg: &Arg) -> hir::Arg {
-    hir::Arg { id: arg.id, pat: lower_pat(&arg.pat), ty: lower_ty(&arg.ty) }
+pub fn lower_arg(_lctx: &LoweringContext, arg: &Arg) -> hir::Arg {
+    hir::Arg {
+        id: arg.id,
+        pat: lower_pat(_lctx, &arg.pat),
+        ty: lower_ty(_lctx, &arg.ty),
+    }
 }
 
-pub fn lower_fn_decl(decl: &FnDecl) -> P<hir::FnDecl> {
+pub fn lower_fn_decl(_lctx: &LoweringContext, decl: &FnDecl) -> P<hir::FnDecl> {
     P(hir::FnDecl {
-        inputs: decl.inputs.iter().map(|x| lower_arg(x)).collect(),
+        inputs: decl.inputs.iter().map(|x| lower_arg(_lctx, x)).collect(),
         output: match decl.output {
-            Return(ref ty) => hir::Return(lower_ty(ty)),
+            Return(ref ty) => hir::Return(lower_ty(_lctx, ty)),
             DefaultReturn(span) => hir::DefaultReturn(span),
-            NoReturn(span) => hir::NoReturn(span)
+            NoReturn(span) => hir::NoReturn(span),
         },
         variadic: decl.variadic,
     })
 }
 
-pub fn lower_ty_param_bound(tpb: &TyParamBound) -> hir::TyParamBound {
+pub fn lower_ty_param_bound(_lctx: &LoweringContext, tpb: &TyParamBound) -> hir::TyParamBound {
     match *tpb {
         TraitTyParamBound(ref ty, modifier) => {
-            hir::TraitTyParamBound(lower_poly_trait_ref(ty), lower_trait_bound_modifier(modifier))
+            hir::TraitTyParamBound(lower_poly_trait_ref(_lctx, ty),
+                                   lower_trait_bound_modifier(_lctx, modifier))
+        }
+        RegionTyParamBound(ref lifetime) => {
+            hir::RegionTyParamBound(lower_lifetime(_lctx, lifetime))
         }
-        RegionTyParamBound(ref lifetime) => hir::RegionTyParamBound(lower_lifetime(lifetime)),
     }
 }
 
-pub fn lower_ty_param(tp: &TyParam) -> hir::TyParam {
+pub fn lower_ty_param(_lctx: &LoweringContext, tp: &TyParam) -> hir::TyParam {
     hir::TyParam {
         id: tp.id,
-        ident: tp.ident,
-        bounds: lower_bounds(&tp.bounds),
-        default: tp.default.as_ref().map(|x| lower_ty(x)),
+        name: tp.ident.name,
+        bounds: lower_bounds(_lctx, &tp.bounds),
+        default: tp.default.as_ref().map(|x| lower_ty(_lctx, x)),
         span: tp.span,
     }
 }
 
-pub fn lower_ty_params(tps: &OwnedSlice<TyParam>) -> OwnedSlice<hir::TyParam> {
-    tps.iter().map(|tp| lower_ty_param(tp)).collect()
+pub fn lower_ty_params(_lctx: &LoweringContext,
+                       tps: &OwnedSlice<TyParam>)
+                       -> OwnedSlice<hir::TyParam> {
+    tps.iter().map(|tp| lower_ty_param(_lctx, tp)).collect()
 }
 
-pub fn lower_lifetime(l: &Lifetime) -> hir::Lifetime {
-    hir::Lifetime { id: l.id, name: l.name, span: l.span }
+pub fn lower_lifetime(_lctx: &LoweringContext, l: &Lifetime) -> hir::Lifetime {
+    hir::Lifetime {
+        id: l.id,
+        name: l.name,
+        span: l.span,
+    }
 }
 
-pub fn lower_lifetime_def(l: &LifetimeDef) -> hir::LifetimeDef {
-    hir::LifetimeDef { lifetime: lower_lifetime(&l.lifetime), bounds: lower_lifetimes(&l.bounds) }
+pub fn lower_lifetime_def(_lctx: &LoweringContext, l: &LifetimeDef) -> hir::LifetimeDef {
+    hir::LifetimeDef {
+        lifetime: lower_lifetime(_lctx, &l.lifetime),
+        bounds: lower_lifetimes(_lctx, &l.bounds),
+    }
 }
 
-pub fn lower_lifetimes(lts: &Vec<Lifetime>) -> Vec<hir::Lifetime> {
-    lts.iter().map(|l| lower_lifetime(l)).collect()
+pub fn lower_lifetimes(_lctx: &LoweringContext, lts: &Vec<Lifetime>) -> Vec<hir::Lifetime> {
+    lts.iter().map(|l| lower_lifetime(_lctx, l)).collect()
 }
 
-pub fn lower_lifetime_defs(lts: &Vec<LifetimeDef>) -> Vec<hir::LifetimeDef> {
-    lts.iter().map(|l| lower_lifetime_def(l)).collect()
+pub fn lower_lifetime_defs(_lctx: &LoweringContext,
+                           lts: &Vec<LifetimeDef>)
+                           -> Vec<hir::LifetimeDef> {
+    lts.iter().map(|l| lower_lifetime_def(_lctx, l)).collect()
 }
 
-pub fn lower_opt_lifetime(o_lt: &Option<Lifetime>) -> Option<hir::Lifetime> {
-    o_lt.as_ref().map(|lt| lower_lifetime(lt))
+pub fn lower_opt_lifetime(_lctx: &LoweringContext,
+                          o_lt: &Option<Lifetime>)
+                          -> Option<hir::Lifetime> {
+    o_lt.as_ref().map(|lt| lower_lifetime(_lctx, lt))
 }
 
-pub fn lower_generics(g: &Generics) -> hir::Generics {
+pub fn lower_generics(_lctx: &LoweringContext, g: &Generics) -> hir::Generics {
     hir::Generics {
-        ty_params: lower_ty_params(&g.ty_params),
-        lifetimes: lower_lifetime_defs(&g.lifetimes),
-        where_clause: lower_where_clause(&g.where_clause),
+        ty_params: lower_ty_params(_lctx, &g.ty_params),
+        lifetimes: lower_lifetime_defs(_lctx, &g.lifetimes),
+        where_clause: lower_where_clause(_lctx, &g.where_clause),
     }
 }
 
-pub fn lower_where_clause(wc: &WhereClause) -> hir::WhereClause {
+pub fn lower_where_clause(_lctx: &LoweringContext, wc: &WhereClause) -> hir::WhereClause {
     hir::WhereClause {
         id: wc.id,
-        predicates: wc.predicates.iter().map(|predicate|
-            lower_where_predicate(predicate)).collect(),
+        predicates: wc.predicates
+                      .iter()
+                      .map(|predicate| lower_where_predicate(_lctx, predicate))
+                      .collect(),
     }
 }
 
-pub fn lower_where_predicate(pred: &WherePredicate) -> hir::WherePredicate {
+pub fn lower_where_predicate(_lctx: &LoweringContext,
+                             pred: &WherePredicate)
+                             -> hir::WherePredicate {
     match *pred {
         WherePredicate::BoundPredicate(WhereBoundPredicate{ ref bound_lifetimes,
                                                             ref bounded_ty,
                                                             ref bounds,
                                                             span}) => {
             hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate {
-                bound_lifetimes: lower_lifetime_defs(bound_lifetimes),
-                bounded_ty: lower_ty(bounded_ty),
-                bounds: bounds.iter().map(|x| lower_ty_param_bound(x)).collect(),
-                span: span
+                bound_lifetimes: lower_lifetime_defs(_lctx, bound_lifetimes),
+                bounded_ty: lower_ty(_lctx, bounded_ty),
+                bounds: bounds.iter().map(|x| lower_ty_param_bound(_lctx, x)).collect(),
+                span: span,
             })
         }
         WherePredicate::RegionPredicate(WhereRegionPredicate{ ref lifetime,
@@ -381,142 +480,161 @@ pub fn lower_where_predicate(pred: &WherePredicate) -> hir::WherePredicate {
                                                               span}) => {
             hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate {
                 span: span,
-                lifetime: lower_lifetime(lifetime),
-                bounds: bounds.iter().map(|bound| lower_lifetime(bound)).collect()
+                lifetime: lower_lifetime(_lctx, lifetime),
+                bounds: bounds.iter().map(|bound| lower_lifetime(_lctx, bound)).collect(),
             })
         }
         WherePredicate::EqPredicate(WhereEqPredicate{ id,
                                                       ref path,
                                                       ref ty,
                                                       span}) => {
-            hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{
+            hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
                 id: id,
-                path: lower_path(path),
-                ty:lower_ty(ty),
-                span: span
+                path: lower_path(_lctx, path),
+                ty: lower_ty(_lctx, ty),
+                span: span,
             })
         }
     }
 }
 
-pub fn lower_struct_def(sd: &StructDef) -> P<hir::StructDef> {
-    P(hir::StructDef {
-        fields: sd.fields.iter().map(|f| lower_struct_field(f)).collect(),
-        ctor_id: sd.ctor_id,
-    })
+pub fn lower_variant_data(_lctx: &LoweringContext, vdata: &VariantData) -> hir::VariantData {
+    match *vdata {
+        VariantData::Struct(ref fields, id) => {
+            hir::VariantData::Struct(fields.iter()
+                                           .map(|f| lower_struct_field(_lctx, f)).collect(), id)
+        }
+        VariantData::Tuple(ref fields, id) => {
+            hir::VariantData::Tuple(fields.iter()
+                                          .map(|f| lower_struct_field(_lctx, f)).collect(), id)
+        }
+        VariantData::Unit(id) => hir::VariantData::Unit(id)
+    }
 }
 
-pub fn lower_trait_ref(p: &TraitRef) -> hir::TraitRef {
-    hir::TraitRef { path: lower_path(&p.path), ref_id: p.ref_id }
+pub fn lower_trait_ref(_lctx: &LoweringContext, p: &TraitRef) -> hir::TraitRef {
+    hir::TraitRef {
+        path: lower_path(_lctx, &p.path),
+        ref_id: p.ref_id,
+    }
 }
 
-pub fn lower_poly_trait_ref(p: &PolyTraitRef) -> hir::PolyTraitRef {
+pub fn lower_poly_trait_ref(_lctx: &LoweringContext, p: &PolyTraitRef) -> hir::PolyTraitRef {
     hir::PolyTraitRef {
-        bound_lifetimes: lower_lifetime_defs(&p.bound_lifetimes),
-        trait_ref: lower_trait_ref(&p.trait_ref),
+        bound_lifetimes: lower_lifetime_defs(_lctx, &p.bound_lifetimes),
+        trait_ref: lower_trait_ref(_lctx, &p.trait_ref),
         span: p.span,
     }
 }
 
-pub fn lower_struct_field(f: &StructField) -> hir::StructField {
+pub fn lower_struct_field(_lctx: &LoweringContext, f: &StructField) -> hir::StructField {
     Spanned {
         node: hir::StructField_ {
             id: f.node.id,
-            kind: lower_struct_field_kind(&f.node.kind),
-            ty: lower_ty(&f.node.ty),
-            attrs: lower_attrs(&f.node.attrs),
+            kind: lower_struct_field_kind(_lctx, &f.node.kind),
+            ty: lower_ty(_lctx, &f.node.ty),
+            attrs: f.node.attrs.clone(),
         },
         span: f.span,
     }
 }
 
-pub fn lower_field(f: &Field) -> hir::Field {
-    hir::Field { ident: f.ident, expr: lower_expr(&f.expr), span: f.span }
+pub fn lower_field(_lctx: &LoweringContext, f: &Field) -> hir::Field {
+    hir::Field {
+        name: respan(f.ident.span, f.ident.node.name),
+        expr: lower_expr(_lctx, &f.expr),
+        span: f.span,
+    }
 }
 
-pub fn lower_mt(mt: &MutTy) -> hir::MutTy {
-    hir::MutTy { ty: lower_ty(&mt.ty), mutbl: lower_mutability(mt.mutbl) }
+pub fn lower_mt(_lctx: &LoweringContext, mt: &MutTy) -> hir::MutTy {
+    hir::MutTy {
+        ty: lower_ty(_lctx, &mt.ty),
+        mutbl: lower_mutability(_lctx, mt.mutbl),
+    }
 }
 
-pub fn lower_opt_bounds(b: &Option<OwnedSlice<TyParamBound>>)
+pub fn lower_opt_bounds(_lctx: &LoweringContext,
+                        b: &Option<OwnedSlice<TyParamBound>>)
                         -> Option<OwnedSlice<hir::TyParamBound>> {
-    b.as_ref().map(|ref bounds| lower_bounds(bounds))
+    b.as_ref().map(|ref bounds| lower_bounds(_lctx, bounds))
 }
 
-fn lower_bounds(bounds: &TyParamBounds) -> hir::TyParamBounds {
-    bounds.iter().map(|bound| lower_ty_param_bound(bound)).collect()
+fn lower_bounds(_lctx: &LoweringContext, bounds: &TyParamBounds) -> hir::TyParamBounds {
+    bounds.iter().map(|bound| lower_ty_param_bound(_lctx, bound)).collect()
 }
 
-fn lower_variant_arg(va: &VariantArg) -> hir::VariantArg {
-    hir::VariantArg { id: va.id, ty: lower_ty(&va.ty) }
-}
-
-pub fn lower_block(b: &Block) -> P<hir::Block> {
+pub fn lower_block(_lctx: &LoweringContext, b: &Block) -> P<hir::Block> {
     P(hir::Block {
         id: b.id,
-        stmts: b.stmts.iter().map(|s| lower_stmt(s)).collect(),
-        expr: b.expr.as_ref().map(|ref x| lower_expr(x)),
-        rules: lower_block_check_mode(&b.rules),
+        stmts: b.stmts.iter().map(|s| lower_stmt(_lctx, s)).collect(),
+        expr: b.expr.as_ref().map(|ref x| lower_expr(_lctx, x)),
+        rules: lower_block_check_mode(_lctx, &b.rules),
         span: b.span,
     })
 }
 
-pub fn lower_item_underscore(i: &Item_) -> hir::Item_ {
+pub fn lower_item_underscore(_lctx: &LoweringContext, i: &Item_) -> hir::Item_ {
     match *i {
         ItemExternCrate(string) => hir::ItemExternCrate(string),
         ItemUse(ref view_path) => {
-            hir::ItemUse(lower_view_path(view_path))
+            hir::ItemUse(lower_view_path(_lctx, view_path))
         }
         ItemStatic(ref t, m, ref e) => {
-            hir::ItemStatic(lower_ty(t), lower_mutability(m), lower_expr(e))
+            hir::ItemStatic(lower_ty(_lctx, t),
+                            lower_mutability(_lctx, m),
+                            lower_expr(_lctx, e))
         }
         ItemConst(ref t, ref e) => {
-            hir::ItemConst(lower_ty(t), lower_expr(e))
+            hir::ItemConst(lower_ty(_lctx, t), lower_expr(_lctx, e))
         }
         ItemFn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
-            hir::ItemFn(
-                lower_fn_decl(decl),
-                lower_unsafety(unsafety),
-                lower_constness(constness),
-                abi,
-                lower_generics(generics),
-                lower_block(body)
-            )
+            hir::ItemFn(lower_fn_decl(_lctx, decl),
+                        lower_unsafety(_lctx, unsafety),
+                        lower_constness(_lctx, constness),
+                        abi,
+                        lower_generics(_lctx, generics),
+                        lower_block(_lctx, body))
         }
-        ItemMod(ref m) => hir::ItemMod(lower_mod(m)),
-        ItemForeignMod(ref nm) => hir::ItemForeignMod(lower_foreign_mod(nm)),
+        ItemMod(ref m) => hir::ItemMod(lower_mod(_lctx, m)),
+        ItemForeignMod(ref nm) => hir::ItemForeignMod(lower_foreign_mod(_lctx, nm)),
         ItemTy(ref t, ref generics) => {
-            hir::ItemTy(lower_ty(t), lower_generics(generics))
+            hir::ItemTy(lower_ty(_lctx, t), lower_generics(_lctx, generics))
         }
         ItemEnum(ref enum_definition, ref generics) => {
-            hir::ItemEnum(
-                hir::EnumDef {
-                    variants: enum_definition.variants.iter().map(|x| lower_variant(x)).collect(),
-                },
-                lower_generics(generics))
+            hir::ItemEnum(hir::EnumDef {
+                              variants: enum_definition.variants
+                                                       .iter()
+                                                       .map(|x| lower_variant(_lctx, x))
+                                                       .collect(),
+                          },
+                          lower_generics(_lctx, generics))
         }
         ItemStruct(ref struct_def, ref generics) => {
-            let struct_def = lower_struct_def(struct_def);
-            hir::ItemStruct(struct_def, lower_generics(generics))
+            let struct_def = lower_variant_data(_lctx, struct_def);
+            hir::ItemStruct(struct_def, lower_generics(_lctx, generics))
         }
         ItemDefaultImpl(unsafety, ref trait_ref) => {
-            hir::ItemDefaultImpl(lower_unsafety(unsafety), lower_trait_ref(trait_ref))
+            hir::ItemDefaultImpl(lower_unsafety(_lctx, unsafety),
+                                 lower_trait_ref(_lctx, trait_ref))
         }
         ItemImpl(unsafety, polarity, ref generics, ref ifce, ref ty, ref impl_items) => {
-            let new_impl_items = impl_items.iter().map(|item| lower_impl_item(item)).collect();
-            let ifce = ifce.as_ref().map(|trait_ref| lower_trait_ref(trait_ref));
-            hir::ItemImpl(lower_unsafety(unsafety),
-                          lower_impl_polarity(polarity),
-                          lower_generics(generics),
+            let new_impl_items = impl_items.iter()
+                                           .map(|item| lower_impl_item(_lctx, item))
+                                           .collect();
+            let ifce = ifce.as_ref().map(|trait_ref| lower_trait_ref(_lctx, trait_ref));
+            hir::ItemImpl(lower_unsafety(_lctx, unsafety),
+                          lower_impl_polarity(_lctx, polarity),
+                          lower_generics(_lctx, generics),
                           ifce,
-                          lower_ty(ty),
+                          lower_ty(_lctx, ty),
                           new_impl_items)
         }
         ItemTrait(unsafety, ref generics, ref bounds, ref items) => {
-            let bounds = lower_bounds(bounds);
-            let items = items.iter().map(|item| lower_trait_item(item)).collect();
-            hir::ItemTrait(lower_unsafety(unsafety),
-                           lower_generics(generics),
+            let bounds = lower_bounds(_lctx, bounds);
+            let items = items.iter().map(|item| lower_trait_item(_lctx, item)).collect();
+            hir::ItemTrait(lower_unsafety(_lctx, unsafety),
+                           lower_generics(_lctx, generics),
                            bounds,
                            items)
         }
@@ -524,73 +642,74 @@ pub fn lower_item_underscore(i: &Item_) -> hir::Item_ {
     }
 }
 
-pub fn lower_trait_item(i: &TraitItem) -> P<hir::TraitItem> {
+pub fn lower_trait_item(_lctx: &LoweringContext, i: &TraitItem) -> P<hir::TraitItem> {
     P(hir::TraitItem {
-            id: i.id,
-            ident: i.ident,
-            attrs: lower_attrs(&i.attrs),
-            node: match i.node {
+        id: i.id,
+        name: i.ident.name,
+        attrs: i.attrs.clone(),
+        node: match i.node {
             ConstTraitItem(ref ty, ref default) => {
-                hir::ConstTraitItem(lower_ty(ty),
-                                    default.as_ref().map(|x| lower_expr(x)))
+                hir::ConstTraitItem(lower_ty(_lctx, ty),
+                                    default.as_ref().map(|x| lower_expr(_lctx, x)))
             }
             MethodTraitItem(ref sig, ref body) => {
-                hir::MethodTraitItem(lower_method_sig(sig),
-                                     body.as_ref().map(|x| lower_block(x)))
+                hir::MethodTraitItem(lower_method_sig(_lctx, sig),
+                                     body.as_ref().map(|x| lower_block(_lctx, x)))
             }
             TypeTraitItem(ref bounds, ref default) => {
-                hir::TypeTraitItem(lower_bounds(bounds),
-                                   default.as_ref().map(|x| lower_ty(x)))
+                hir::TypeTraitItem(lower_bounds(_lctx, bounds),
+                                   default.as_ref().map(|x| lower_ty(_lctx, x)))
             }
         },
-            span: i.span,
-        })
+        span: i.span,
+    })
 }
 
-pub fn lower_impl_item(i: &ImplItem) -> P<hir::ImplItem> {
+pub fn lower_impl_item(_lctx: &LoweringContext, i: &ImplItem) -> P<hir::ImplItem> {
     P(hir::ImplItem {
-            id: i.id,
-            ident: i.ident,
-            attrs: lower_attrs(&i.attrs),
-            vis: lower_visibility(i.vis),
-            node: match i.node  {
+        id: i.id,
+        name: i.ident.name,
+        attrs: i.attrs.clone(),
+        vis: lower_visibility(_lctx, i.vis),
+        node: match i.node {
             ConstImplItem(ref ty, ref expr) => {
-                hir::ConstImplItem(lower_ty(ty), lower_expr(expr))
+                hir::ConstImplItem(lower_ty(_lctx, ty), lower_expr(_lctx, expr))
             }
             MethodImplItem(ref sig, ref body) => {
-                hir::MethodImplItem(lower_method_sig(sig),
-                                    lower_block(body))
+                hir::MethodImplItem(lower_method_sig(_lctx, sig),
+                                    lower_block(_lctx, body))
             }
-            TypeImplItem(ref ty) => hir::TypeImplItem(lower_ty(ty)),
+            TypeImplItem(ref ty) => hir::TypeImplItem(lower_ty(_lctx, ty)),
             MacImplItem(..) => panic!("Shouldn't exist any more"),
         },
-            span: i.span,
-        })
+        span: i.span,
+    })
 }
 
-pub fn lower_mod(m: &Mod) -> hir::Mod {
-    hir::Mod { inner: m.inner, items: m.items.iter().map(|x| lower_item(x)).collect() }
+pub fn lower_mod(_lctx: &LoweringContext, m: &Mod) -> hir::Mod {
+    hir::Mod {
+        inner: m.inner,
+        items: m.items.iter().map(|x| lower_item(_lctx, x)).collect(),
+    }
 }
 
-pub fn lower_crate(c: &Crate) -> hir::Crate {
-    let config = lower_meta_items(&c.config);
-
+pub fn lower_crate(_lctx: &LoweringContext, c: &Crate) -> hir::Crate {
     hir::Crate {
-        module: lower_mod(&c.module),
-        attrs: lower_attrs(&c.attrs),
-        config: config,
+        module: lower_mod(_lctx, &c.module),
+        attrs: c.attrs.clone(),
+        config: c.config.clone(),
         span: c.span,
-        exported_macros: c.exported_macros.iter().map(|m| lower_macro_def(m)).collect(),
+        exported_macros: c.exported_macros.iter().map(|m| lower_macro_def(_lctx, m)).collect(),
     }
 }
 
-pub fn lower_macro_def(m: &MacroDef) -> hir::MacroDef {
+pub fn lower_macro_def(_lctx: &LoweringContext, m: &MacroDef) -> hir::MacroDef {
     hir::MacroDef {
-        ident: m.ident,
-        attrs: m.attrs.iter().map(|a| lower_attribute(a)).collect(),
+        name: m.ident.name,
+        attrs: m.attrs.clone(),
         id: m.id,
         span: m.span,
-        imported_from: m.imported_from,
+        imported_from: m.imported_from.map(|x| x.name),
         export: m.export,
         use_locally: m.use_locally,
         allow_internal_unstable: m.allow_internal_unstable,
@@ -599,108 +718,77 @@ pub fn lower_macro_def(m: &MacroDef) -> hir::MacroDef {
 }
 
 // fold one item into possibly many items
-pub fn lower_item(i: &Item) -> P<hir::Item> {
-    P(lower_item_simple(i))
+pub fn lower_item(_lctx: &LoweringContext, i: &Item) -> P<hir::Item> {
+    P(lower_item_simple(_lctx, i))
 }
 
 // fold one item into exactly one item
-pub fn lower_item_simple(i: &Item) -> hir::Item {
-    let node = lower_item_underscore(&i.node);
+pub fn lower_item_simple(_lctx: &LoweringContext, i: &Item) -> hir::Item {
+    let node = lower_item_underscore(_lctx, &i.node);
 
     hir::Item {
         id: i.id,
-        ident: i.ident,
-        attrs: lower_attrs(&i.attrs),
+        name: i.ident.name,
+        attrs: i.attrs.clone(),
         node: node,
-        vis: lower_visibility(i.vis),
+        vis: lower_visibility(_lctx, i.vis),
         span: i.span,
     }
 }
 
-pub fn lower_foreign_item(i: &ForeignItem) -> P<hir::ForeignItem> {
+pub fn lower_foreign_item(_lctx: &LoweringContext, i: &ForeignItem) -> P<hir::ForeignItem> {
     P(hir::ForeignItem {
-            id: i.id,
-            ident: i.ident,
-            attrs: lower_attrs(&i.attrs),
-            node: match i.node {
+        id: i.id,
+        name: i.ident.name,
+        attrs: i.attrs.clone(),
+        node: match i.node {
             ForeignItemFn(ref fdec, ref generics) => {
-                hir::ForeignItemFn(lower_fn_decl(fdec), lower_generics(generics))
+                hir::ForeignItemFn(lower_fn_decl(_lctx, fdec),
+                                   lower_generics(_lctx, generics))
             }
             ForeignItemStatic(ref t, m) => {
-                hir::ForeignItemStatic(lower_ty(t), m)
+                hir::ForeignItemStatic(lower_ty(_lctx, t), m)
             }
         },
-            vis: lower_visibility(i.vis),
-            span: i.span,
-        })
+        vis: lower_visibility(_lctx, i.vis),
+        span: i.span,
+    })
 }
 
-pub fn lower_method_sig(sig: &MethodSig) -> hir::MethodSig {
+pub fn lower_method_sig(_lctx: &LoweringContext, sig: &MethodSig) -> hir::MethodSig {
     hir::MethodSig {
-        generics: lower_generics(&sig.generics),
+        generics: lower_generics(_lctx, &sig.generics),
         abi: sig.abi,
-        explicit_self: lower_explicit_self(&sig.explicit_self),
-        unsafety: lower_unsafety(sig.unsafety),
-        constness: lower_constness(sig.constness),
-        decl: lower_fn_decl(&sig.decl),
+        explicit_self: lower_explicit_self(_lctx, &sig.explicit_self),
+        unsafety: lower_unsafety(_lctx, sig.unsafety),
+        constness: lower_constness(_lctx, sig.constness),
+        decl: lower_fn_decl(_lctx, &sig.decl),
     }
 }
 
-pub fn lower_unsafety(u: Unsafety) -> hir::Unsafety {
+pub fn lower_unsafety(_lctx: &LoweringContext, u: Unsafety) -> hir::Unsafety {
     match u {
         Unsafety::Unsafe => hir::Unsafety::Unsafe,
         Unsafety::Normal => hir::Unsafety::Normal,
     }
 }
 
-pub fn lower_constness(c: Constness) -> hir::Constness {
+pub fn lower_constness(_lctx: &LoweringContext, c: Constness) -> hir::Constness {
     match c {
         Constness::Const => hir::Constness::Const,
         Constness::NotConst => hir::Constness::NotConst,
     }
 }
 
-pub fn lower_lit(l: &Lit) -> hir::Lit {
-    Spanned {
-        node: match l.node {
-            LitStr(ref i, s) => hir::LitStr(i.clone(), lower_string_style(s)),
-            LitByteStr(ref b) => hir::LitByteStr(b.clone()),
-            LitByte(u) => hir::LitByte(u),
-            LitChar(c) => hir::LitChar(c),
-            LitInt(u, ref t) => hir::LitInt(u, lower_lit_int_type(t)),
-            LitFloat(ref i, t) => hir::LitFloat(i.clone(), lower_float_ty(t)),
-            LitFloatUnsuffixed(ref i) => hir::LitFloatUnsuffixed(i.clone()),
-            LitBool(b) => hir::LitBool(b),
-        },
-        span: l.span,
-    }
-}
-
-pub fn unlower_lit(l: &hir::Lit) -> Lit {
-    Spanned {
-        node: match l.node {
-            hir::LitStr(ref i, s) => LitStr(i.clone(), unlower_string_style(s)),
-            hir::LitByteStr(ref b) => LitByteStr(b.clone()),
-            hir::LitByte(u) => LitByte(u),
-            hir::LitChar(c) => LitChar(c),
-            hir::LitInt(u, ref t) => LitInt(u, unlower_lit_int_type(t)),
-            hir::LitFloat(ref i, t) => LitFloat(i.clone(), unlower_float_ty(t)),
-            hir::LitFloatUnsuffixed(ref i) => LitFloatUnsuffixed(i.clone()),
-            hir::LitBool(b) => LitBool(b),
-        },
-        span: l.span,
-    }
-}
-pub fn lower_unop(u: UnOp) -> hir::UnOp {
+pub fn lower_unop(_lctx: &LoweringContext, u: UnOp) -> hir::UnOp {
     match u {
-        UnUniq => hir::UnUniq,
         UnDeref => hir::UnDeref,
         UnNot => hir::UnNot,
         UnNeg => hir::UnNeg,
     }
 }
 
-pub fn lower_binop(b: BinOp) -> hir::BinOp {
+pub fn lower_binop(_lctx: &LoweringContext, b: BinOp) -> hir::BinOp {
     Spanned {
         node: match b.node {
             BiAdd => hir::BiAdd,
@@ -726,154 +814,350 @@ pub fn lower_binop(b: BinOp) -> hir::BinOp {
     }
 }
 
-pub fn lower_pat(p: &Pat) -> P<hir::Pat> {
+pub fn lower_pat(_lctx: &LoweringContext, p: &Pat) -> P<hir::Pat> {
     P(hir::Pat {
-            id: p.id,
-            node: match p.node {
-            PatWild(k) => hir::PatWild(lower_pat_wild_kind(k)),
+        id: p.id,
+        node: match p.node {
+            PatWild(k) => hir::PatWild(lower_pat_wild_kind(_lctx, k)),
             PatIdent(ref binding_mode, pth1, ref sub) => {
-                hir::PatIdent(lower_binding_mode(binding_mode),
-                        pth1,
-                        sub.as_ref().map(|x| lower_pat(x)))
+                hir::PatIdent(lower_binding_mode(_lctx, binding_mode),
+                              pth1,
+                              sub.as_ref().map(|x| lower_pat(_lctx, x)))
             }
-            PatLit(ref e) => hir::PatLit(lower_expr(e)),
+            PatLit(ref e) => hir::PatLit(lower_expr(_lctx, e)),
             PatEnum(ref pth, ref pats) => {
-                hir::PatEnum(lower_path(pth),
-                        pats.as_ref().map(|pats| pats.iter().map(|x| lower_pat(x)).collect()))
+                hir::PatEnum(lower_path(_lctx, pth),
+                             pats.as_ref()
+                                 .map(|pats| pats.iter().map(|x| lower_pat(_lctx, x)).collect()))
             }
             PatQPath(ref qself, ref pth) => {
                 let qself = hir::QSelf {
-                    ty: lower_ty(&qself.ty),
+                    ty: lower_ty(_lctx, &qself.ty),
                     position: qself.position,
                 };
-                hir::PatQPath(qself, lower_path(pth))
+                hir::PatQPath(qself, lower_path(_lctx, pth))
             }
             PatStruct(ref pth, ref fields, etc) => {
-                let pth = lower_path(pth);
-                let fs = fields.iter().map(|f| {
-                    Spanned { span: f.span,
-                              node: hir::FieldPat {
-                                  ident: f.node.ident,
-                                  pat: lower_pat(&f.node.pat),
-                                  is_shorthand: f.node.is_shorthand,
-                              }}
-                }).collect();
+                let pth = lower_path(_lctx, pth);
+                let fs = fields.iter()
+                               .map(|f| {
+                                   Spanned {
+                                       span: f.span,
+                                       node: hir::FieldPat {
+                                           name: f.node.ident.name,
+                                           pat: lower_pat(_lctx, &f.node.pat),
+                                           is_shorthand: f.node.is_shorthand,
+                                       },
+                                   }
+                               })
+                               .collect();
                 hir::PatStruct(pth, fs, etc)
             }
-            PatTup(ref elts) => hir::PatTup(elts.iter().map(|x| lower_pat(x)).collect()),
-            PatBox(ref inner) => hir::PatBox(lower_pat(inner)),
-            PatRegion(ref inner, mutbl) => hir::PatRegion(lower_pat(inner),
-                                                          lower_mutability(mutbl)),
+            PatTup(ref elts) => hir::PatTup(elts.iter().map(|x| lower_pat(_lctx, x)).collect()),
+            PatBox(ref inner) => hir::PatBox(lower_pat(_lctx, inner)),
+            PatRegion(ref inner, mutbl) => hir::PatRegion(lower_pat(_lctx, inner),
+                                                          lower_mutability(_lctx, mutbl)),
             PatRange(ref e1, ref e2) => {
-                hir::PatRange(lower_expr(e1), lower_expr(e2))
-            },
+                hir::PatRange(lower_expr(_lctx, e1), lower_expr(_lctx, e2))
+            }
             PatVec(ref before, ref slice, ref after) => {
-                hir::PatVec(before.iter().map(|x| lower_pat(x)).collect(),
-                       slice.as_ref().map(|x| lower_pat(x)),
-                       after.iter().map(|x| lower_pat(x)).collect())
+                hir::PatVec(before.iter().map(|x| lower_pat(_lctx, x)).collect(),
+                            slice.as_ref().map(|x| lower_pat(_lctx, x)),
+                            after.iter().map(|x| lower_pat(_lctx, x)).collect())
             }
             PatMac(_) => panic!("Shouldn't exist here"),
         },
-            span: p.span,
-        })
+        span: p.span,
+    })
+}
+
+// RAII utility for setting and unsetting the cached id.
+struct CachedIdSetter<'a> {
+    reset: bool,
+    lctx: &'a LoweringContext<'a>,
+}
+
+impl<'a> CachedIdSetter<'a> {
+    fn new(lctx: &'a LoweringContext, expr_id: NodeId) -> CachedIdSetter<'a> {
+        // Only reset the id if it was previously 0, i.e., was not cached.
+        // If it was cached, we are in a nested node, but our id count will
+        // still count towards the parent's count.
+        let reset_cached_id = lctx.cached_id.get() == 0;
+
+        let id_cache: &mut HashMap<_, _> = &mut lctx.id_cache.borrow_mut();
+
+        if id_cache.contains_key(&expr_id) {
+            let cached_id = lctx.cached_id.get();
+            if cached_id == 0 {
+                // We're entering a node where we need to track ids, but are not
+                // yet tracking.
+                lctx.cached_id.set(id_cache[&expr_id]);
+                lctx.gensym_key.set(id_cache[&expr_id]);
+            } else {
+                // We're already tracking - check that the tracked id is the same
+                // as the expected id.
+                assert!(cached_id == id_cache[&expr_id], "id mismatch");
+            }
+        } else {
+            let next_id = lctx.id_assigner.peek_node_id();
+            id_cache.insert(expr_id, next_id);
+            lctx.gensym_key.set(next_id);
+        }
+
+        CachedIdSetter {
+            reset: reset_cached_id,
+            lctx: lctx,
+        }
+    }
 }
 
-pub fn lower_expr(e: &Expr) -> P<hir::Expr> {
+impl<'a> Drop for CachedIdSetter<'a> {
+    fn drop(&mut self) {
+        if self.reset {
+            self.lctx.cached_id.set(0);
+            self.lctx.gensym_key.set(0);
+        }
+    }
+}
+
+pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
     P(hir::Expr {
-            id: e.id,
-            node: match e.node {
-                ExprBox(ref p, ref e) => {
-                    hir::ExprBox(p.as_ref().map(|e| lower_expr(e)), lower_expr(e))
-                }
-                ExprVec(ref exprs) => {
-                    hir::ExprVec(exprs.iter().map(|x| lower_expr(x)).collect())
-                }
-                ExprRepeat(ref expr, ref count) => {
-                    hir::ExprRepeat(lower_expr(expr), lower_expr(count))
-                }
-                ExprTup(ref elts) => hir::ExprTup(elts.iter().map(|x| lower_expr(x)).collect()),
-                ExprCall(ref f, ref args) => {
-                    hir::ExprCall(lower_expr(f),
-                             args.iter().map(|x| lower_expr(x)).collect())
-                }
-                ExprMethodCall(i, ref tps, ref args) => {
-                    hir::ExprMethodCall(
-                        i,
-                        tps.iter().map(|x| lower_ty(x)).collect(),
-                        args.iter().map(|x| lower_expr(x)).collect())
-                }
-                ExprBinary(binop, ref lhs, ref rhs) => {
-                    hir::ExprBinary(lower_binop(binop),
-                            lower_expr(lhs),
-                            lower_expr(rhs))
-                }
-                ExprUnary(op, ref ohs) => {
-                    hir::ExprUnary(lower_unop(op), lower_expr(ohs))
-                }
-                ExprLit(ref l) => hir::ExprLit(P(lower_lit(l))),
-                ExprCast(ref expr, ref ty) => {
-                    hir::ExprCast(lower_expr(expr), lower_ty(ty))
-                }
-                ExprAddrOf(m, ref ohs) => hir::ExprAddrOf(lower_mutability(m), lower_expr(ohs)),
-                ExprIf(ref cond, ref tr, ref fl) => {
-                    hir::ExprIf(lower_expr(cond),
-                           lower_block(tr),
-                           fl.as_ref().map(|x| lower_expr(x)))
-                }
-                ExprWhile(ref cond, ref body, opt_ident) => {
-                    hir::ExprWhile(lower_expr(cond),
-                              lower_block(body),
-                              opt_ident)
-                }
-                ExprLoop(ref body, opt_ident) => {
-                    hir::ExprLoop(lower_block(body),
-                            opt_ident)
-                }
-                ExprMatch(ref expr, ref arms, ref source) => {
-                    hir::ExprMatch(lower_expr(expr),
-                            arms.iter().map(|x| lower_arm(x)).collect(),
-                            lower_match_source(source))
-                }
-                ExprClosure(capture_clause, ref decl, ref body) => {
-                    hir::ExprClosure(lower_capture_clause(capture_clause),
-                                lower_fn_decl(decl),
-                                lower_block(body))
-                }
-                ExprBlock(ref blk) => hir::ExprBlock(lower_block(blk)),
-                ExprAssign(ref el, ref er) => {
-                    hir::ExprAssign(lower_expr(el), lower_expr(er))
-                }
-                ExprAssignOp(op, ref el, ref er) => {
-                    hir::ExprAssignOp(lower_binop(op),
-                                lower_expr(el),
-                                lower_expr(er))
-                }
-                ExprField(ref el, ident) => {
-                    hir::ExprField(lower_expr(el), ident)
-                }
-                ExprTupField(ref el, ident) => {
-                    hir::ExprTupField(lower_expr(el), ident)
-                }
-                ExprIndex(ref el, ref er) => {
-                    hir::ExprIndex(lower_expr(el), lower_expr(er))
-                }
-                ExprRange(ref e1, ref e2) => {
-                    hir::ExprRange(e1.as_ref().map(|x| lower_expr(x)),
-                              e2.as_ref().map(|x| lower_expr(x)))
-                }
-                ExprPath(ref qself, ref path) => {
-                    let qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
-                        hir::QSelf {
-                            ty: lower_ty(ty),
-                            position: position
+        id: e.id,
+        node: match e.node {
+            // Issue #22181:
+            // Eventually a desugaring for `box EXPR`
+            // (similar to the desugaring above for `in PLACE BLOCK`)
+            // should go here, desugaring
+            //
+            // to:
+            //
+            // let mut place = BoxPlace::make_place();
+            // let raw_place = Place::pointer(&mut place);
+            // let value = $value;
+            // unsafe {
+            //     ::std::ptr::write(raw_place, value);
+            //     Boxed::finalize(place)
+            // }
+            //
+            // But for now there are type-inference issues doing that.
+            ExprBox(ref e) => {
+                hir::ExprBox(lower_expr(lctx, e))
+            }
+
+            // Desugar ExprBox: `in (PLACE) EXPR`
+            ExprInPlace(ref placer, ref value_expr) => {
+                // to:
+                //
+                // let p = PLACE;
+                // let mut place = Placer::make_place(p);
+                // let raw_place = Place::pointer(&mut place);
+                // push_unsafe!({
+                //     std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
+                //     InPlace::finalize(place)
+                // })
+                let _old_cached = CachedIdSetter::new(lctx, e.id);
+
+                let placer_expr = lower_expr(lctx, placer);
+                let value_expr = lower_expr(lctx, value_expr);
+
+                let placer_ident = lctx.str_to_ident("placer");
+                let agent_ident = lctx.str_to_ident("place");
+                let p_ptr_ident = lctx.str_to_ident("p_ptr");
+
+                let make_place = ["ops", "Placer", "make_place"];
+                let place_pointer = ["ops", "Place", "pointer"];
+                let move_val_init = ["intrinsics", "move_val_init"];
+                let inplace_finalize = ["ops", "InPlace", "finalize"];
+
+                let make_call = |lctx, p, args| {
+                    let path = core_path(lctx, e.span, p);
+                    let path = expr_path(lctx, path);
+                    expr_call(lctx, e.span, path, args)
+                };
+
+                let mk_stmt_let = |lctx, bind, expr| stmt_let(lctx, e.span, false, bind, expr);
+                let mk_stmt_let_mut = |lctx, bind, expr| stmt_let(lctx, e.span, true, bind, expr);
+
+                // let placer = <placer_expr> ;
+                let s1 = mk_stmt_let(lctx,
+                                     placer_ident,
+                                     signal_block_expr(lctx,
+                                                       vec![],
+                                                       placer_expr,
+                                                       e.span,
+                                                       hir::PopUnstableBlock));
+
+                // let mut place = Placer::make_place(placer);
+                let s2 = {
+                    let call = make_call(lctx,
+                                         &make_place,
+                                         vec![expr_ident(lctx, e.span, placer_ident)]);
+                    mk_stmt_let_mut(lctx, agent_ident, call)
+                };
+
+                // let p_ptr = Place::pointer(&mut place);
+                let s3 = {
+                    let args = vec![expr_mut_addr_of(lctx,
+                                                     e.span,
+                                                     expr_ident(lctx, e.span, agent_ident))];
+                    let call = make_call(lctx, &place_pointer, args);
+                    mk_stmt_let(lctx, p_ptr_ident, call)
+                };
+
+                // pop_unsafe!(EXPR));
+                let pop_unsafe_expr =
+                    signal_block_expr(lctx,
+                                      vec![],
+                                      signal_block_expr(lctx,
+                                                        vec![],
+                                                        value_expr,
+                                                        e.span,
+                                                        hir::PopUnstableBlock),
+                                      e.span,
+                                      hir::PopUnsafeBlock(hir::CompilerGenerated));
+
+                // push_unsafe!({
+                //     std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
+                //     InPlace::finalize(place)
+                // })
+                let expr = {
+                    let call_move_val_init = hir::StmtSemi(make_call(lctx,
+                                                    &move_val_init,
+                                                    vec![expr_ident(lctx, e.span, p_ptr_ident),
+                                                         pop_unsafe_expr]),
+                                                           lctx.next_id());
+                    let call_move_val_init = respan(e.span, call_move_val_init);
+
+                    let call = make_call(lctx,
+                                         &inplace_finalize,
+                                         vec![expr_ident(lctx, e.span, agent_ident)]);
+                    signal_block_expr(lctx,
+                                      vec![P(call_move_val_init)],
+                                      call,
+                                      e.span,
+                                      hir::PushUnsafeBlock(hir::CompilerGenerated))
+                };
+
+                return signal_block_expr(lctx,
+                                         vec![s1, s2, s3],
+                                         expr,
+                                         e.span,
+                                         hir::PushUnstableBlock);
+            }
+
+            ExprVec(ref exprs) => {
+                hir::ExprVec(exprs.iter().map(|x| lower_expr(lctx, x)).collect())
+            }
+            ExprRepeat(ref expr, ref count) => {
+                hir::ExprRepeat(lower_expr(lctx, expr), lower_expr(lctx, count))
+            }
+            ExprTup(ref elts) => {
+                hir::ExprTup(elts.iter().map(|x| lower_expr(lctx, x)).collect())
+            }
+            ExprCall(ref f, ref args) => {
+                hir::ExprCall(lower_expr(lctx, f),
+                              args.iter().map(|x| lower_expr(lctx, x)).collect())
+            }
+            ExprMethodCall(i, ref tps, ref args) => {
+                hir::ExprMethodCall(respan(i.span, i.node.name),
+                                    tps.iter().map(|x| lower_ty(lctx, x)).collect(),
+                                    args.iter().map(|x| lower_expr(lctx, x)).collect())
+            }
+            ExprBinary(binop, ref lhs, ref rhs) => {
+                hir::ExprBinary(lower_binop(lctx, binop),
+                                lower_expr(lctx, lhs),
+                                lower_expr(lctx, rhs))
+            }
+            ExprUnary(op, ref ohs) => {
+                hir::ExprUnary(lower_unop(lctx, op), lower_expr(lctx, ohs))
+            }
+            ExprLit(ref l) => hir::ExprLit(P((**l).clone())),
+            ExprCast(ref expr, ref ty) => {
+                hir::ExprCast(lower_expr(lctx, expr), lower_ty(lctx, ty))
+            }
+            ExprAddrOf(m, ref ohs) => {
+                hir::ExprAddrOf(lower_mutability(lctx, m), lower_expr(lctx, ohs))
+            }
+            // More complicated than you might expect because the else branch
+            // might be `if let`.
+            ExprIf(ref cond, ref blk, ref else_opt) => {
+                let else_opt = else_opt.as_ref().map(|els| {
+                    match els.node {
+                        ExprIfLet(..) => {
+                            let _old_cached = CachedIdSetter::new(lctx, e.id);
+                            // wrap the if-let expr in a block
+                            let span = els.span;
+                            let blk = P(hir::Block {
+                                stmts: vec![],
+                                expr: Some(lower_expr(lctx, els)),
+                                id: lctx.next_id(),
+                                rules: hir::DefaultBlock,
+                                span: span,
+                            });
+                            expr_block(lctx, blk)
                         }
-                    });
-                    hir::ExprPath(qself, lower_path(path))
-                }
-                ExprBreak(opt_ident) => hir::ExprBreak(opt_ident),
-                ExprAgain(opt_ident) => hir::ExprAgain(opt_ident),
-                ExprRet(ref e) => hir::ExprRet(e.as_ref().map(|x| lower_expr(x))),
-                ExprInlineAsm(InlineAsm {
+                        _ => lower_expr(lctx, els),
+                    }
+                });
+
+                hir::ExprIf(lower_expr(lctx, cond),
+                            lower_block(lctx, blk),
+                            else_opt)
+            }
+            ExprWhile(ref cond, ref body, opt_ident) => {
+                hir::ExprWhile(lower_expr(lctx, cond),
+                               lower_block(lctx, body),
+                               opt_ident)
+            }
+            ExprLoop(ref body, opt_ident) => {
+                hir::ExprLoop(lower_block(lctx, body), opt_ident)
+            }
+            ExprMatch(ref expr, ref arms) => {
+                hir::ExprMatch(lower_expr(lctx, expr),
+                               arms.iter().map(|x| lower_arm(lctx, x)).collect(),
+                               hir::MatchSource::Normal)
+            }
+            ExprClosure(capture_clause, ref decl, ref body) => {
+                hir::ExprClosure(lower_capture_clause(lctx, capture_clause),
+                                 lower_fn_decl(lctx, decl),
+                                 lower_block(lctx, body))
+            }
+            ExprBlock(ref blk) => hir::ExprBlock(lower_block(lctx, blk)),
+            ExprAssign(ref el, ref er) => {
+                hir::ExprAssign(lower_expr(lctx, el), lower_expr(lctx, er))
+            }
+            ExprAssignOp(op, ref el, ref er) => {
+                hir::ExprAssignOp(lower_binop(lctx, op),
+                                  lower_expr(lctx, el),
+                                  lower_expr(lctx, er))
+            }
+            ExprField(ref el, ident) => {
+                hir::ExprField(lower_expr(lctx, el),
+                               respan(ident.span, ident.node.name))
+            }
+            ExprTupField(ref el, ident) => {
+                hir::ExprTupField(lower_expr(lctx, el), ident)
+            }
+            ExprIndex(ref el, ref er) => {
+                hir::ExprIndex(lower_expr(lctx, el), lower_expr(lctx, er))
+            }
+            ExprRange(ref e1, ref e2) => {
+                hir::ExprRange(e1.as_ref().map(|x| lower_expr(lctx, x)),
+                               e2.as_ref().map(|x| lower_expr(lctx, x)))
+            }
+            ExprPath(ref qself, ref path) => {
+                let qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
+                    hir::QSelf {
+                        ty: lower_ty(lctx, ty),
+                        position: position,
+                    }
+                });
+                hir::ExprPath(qself, lower_path(lctx, path))
+            }
+            ExprBreak(opt_ident) => hir::ExprBreak(opt_ident),
+            ExprAgain(opt_ident) => hir::ExprAgain(opt_ident),
+            ExprRet(ref e) => hir::ExprRet(e.as_ref().map(|x| lower_expr(lctx, x))),
+            ExprInlineAsm(InlineAsm {
                     ref inputs,
                     ref outputs,
                     ref asm,
@@ -884,250 +1168,690 @@ pub fn lower_expr(e: &Expr) -> P<hir::Expr> {
                     dialect,
                     expn_id,
                 }) => hir::ExprInlineAsm(hir::InlineAsm {
-                    inputs: inputs.iter().map(|&(ref c, ref input)| {
-                        (c.clone(), lower_expr(input))
-                    }).collect(),
-                    outputs: outputs.iter().map(|&(ref c, ref out, ref is_rw)| {
-                        (c.clone(), lower_expr(out), *is_rw)
-                    }).collect(),
-                    asm: asm.clone(),
-                    asm_str_style: lower_string_style(asm_str_style),
-                    clobbers: clobbers.clone(),
-                    volatile: volatile,
-                    alignstack: alignstack,
-                    dialect: lower_asm_dialect(dialect),
-                    expn_id: expn_id,
-                }),
-                ExprStruct(ref path, ref fields, ref maybe_expr) => {
-                    hir::ExprStruct(lower_path(path),
-                            fields.iter().map(|x| lower_field(x)).collect(),
-                            maybe_expr.as_ref().map(|x| lower_expr(x)))
-                },
-                ExprParen(ref ex) => hir::ExprParen(lower_expr(ex)),
-                ExprIfLet(..) |
-                ExprWhileLet(..) |
-                ExprForLoop(..) |
-                ExprMac(_) => panic!("Shouldn't exist here"),
-            },
-            span: e.span,
-        })
-}
-
-pub fn lower_stmt(s: &Stmt) -> P<hir::Stmt> {
+                inputs: inputs.iter()
+                              .map(|&(ref c, ref input)| (c.clone(), lower_expr(lctx, input)))
+                              .collect(),
+                outputs: outputs.iter()
+                                .map(|&(ref c, ref out, ref is_rw)| {
+                                    (c.clone(), lower_expr(lctx, out), *is_rw)
+                                })
+                                .collect(),
+                asm: asm.clone(),
+                asm_str_style: asm_str_style,
+                clobbers: clobbers.clone(),
+                volatile: volatile,
+                alignstack: alignstack,
+                dialect: dialect,
+                expn_id: expn_id,
+            }),
+            ExprStruct(ref path, ref fields, ref maybe_expr) => {
+                hir::ExprStruct(lower_path(lctx, path),
+                                fields.iter().map(|x| lower_field(lctx, x)).collect(),
+                                maybe_expr.as_ref().map(|x| lower_expr(lctx, x)))
+            }
+            ExprParen(ref ex) => {
+                return lower_expr(lctx, ex);
+            }
+
+            // Desugar ExprIfLet
+            // From: `if let <pat> = <sub_expr> <body> [<else_opt>]`
+            ExprIfLet(ref pat, ref sub_expr, ref body, ref else_opt) => {
+                // to:
+                //
+                //   match <sub_expr> {
+                //     <pat> => <body>,
+                //     [_ if <else_opt_if_cond> => <else_opt_if_body>,]
+                //     _ => [<else_opt> | ()]
+                //   }
+
+                let _old_cached = CachedIdSetter::new(lctx, e.id);
+
+                // `<pat> => <body>`
+                let pat_arm = {
+                    let body_expr = expr_block(lctx, lower_block(lctx, body));
+                    arm(vec![lower_pat(lctx, pat)], body_expr)
+                };
+
+                // `[_ if <else_opt_if_cond> => <else_opt_if_body>,]`
+                let mut else_opt = else_opt.as_ref().map(|e| lower_expr(lctx, e));
+                let else_if_arms = {
+                    let mut arms = vec![];
+                    loop {
+                        let else_opt_continue = else_opt.and_then(|els| {
+                            els.and_then(|els| {
+                                match els.node {
+                                    // else if
+                                    hir::ExprIf(cond, then, else_opt) => {
+                                        let pat_under = pat_wild(lctx, e.span);
+                                        arms.push(hir::Arm {
+                                            attrs: vec![],
+                                            pats: vec![pat_under],
+                                            guard: Some(cond),
+                                            body: expr_block(lctx, then),
+                                        });
+                                        else_opt.map(|else_opt| (else_opt, true))
+                                    }
+                                    _ => Some((P(els), false)),
+                                }
+                            })
+                        });
+                        match else_opt_continue {
+                            Some((e, true)) => {
+                                else_opt = Some(e);
+                            }
+                            Some((e, false)) => {
+                                else_opt = Some(e);
+                                break;
+                            }
+                            None => {
+                                else_opt = None;
+                                break;
+                            }
+                        }
+                    }
+                    arms
+                };
+
+                let contains_else_clause = else_opt.is_some();
+
+                // `_ => [<else_opt> | ()]`
+                let else_arm = {
+                    let pat_under = pat_wild(lctx, e.span);
+                    let else_expr = else_opt.unwrap_or_else(|| expr_tuple(lctx, e.span, vec![]));
+                    arm(vec![pat_under], else_expr)
+                };
+
+                let mut arms = Vec::with_capacity(else_if_arms.len() + 2);
+                arms.push(pat_arm);
+                arms.extend(else_if_arms);
+                arms.push(else_arm);
+
+                let match_expr = expr(lctx,
+                                      e.span,
+                                      hir::ExprMatch(lower_expr(lctx, sub_expr),
+                                                     arms,
+                                                     hir::MatchSource::IfLetDesugar {
+                                                         contains_else_clause: contains_else_clause,
+                                                     }));
+                return match_expr;
+            }
+
+            // Desugar ExprWhileLet
+            // From: `[opt_ident]: while let <pat> = <sub_expr> <body>`
+            ExprWhileLet(ref pat, ref sub_expr, ref body, opt_ident) => {
+                // to:
+                //
+                //   [opt_ident]: loop {
+                //     match <sub_expr> {
+                //       <pat> => <body>,
+                //       _ => break
+                //     }
+                //   }
+
+                let _old_cached = CachedIdSetter::new(lctx, e.id);
+
+                // `<pat> => <body>`
+                let pat_arm = {
+                    let body_expr = expr_block(lctx, lower_block(lctx, body));
+                    arm(vec![lower_pat(lctx, pat)], body_expr)
+                };
+
+                // `_ => break`
+                let break_arm = {
+                    let pat_under = pat_wild(lctx, e.span);
+                    let break_expr = expr_break(lctx, e.span);
+                    arm(vec![pat_under], break_expr)
+                };
+
+                // `match <sub_expr> { ... }`
+                let arms = vec![pat_arm, break_arm];
+                let match_expr = expr(lctx,
+                                      e.span,
+                                      hir::ExprMatch(lower_expr(lctx, sub_expr),
+                                                     arms,
+                                                     hir::MatchSource::WhileLetDesugar));
+
+                // `[opt_ident]: loop { ... }`
+                let loop_block = block_expr(lctx, match_expr);
+                return expr(lctx, e.span, hir::ExprLoop(loop_block, opt_ident));
+            }
+
+            // Desugar ExprForLoop
+            // From: `[opt_ident]: for <pat> in <head> <body>`
+            ExprForLoop(ref pat, ref head, ref body, opt_ident) => {
+                // to:
+                //
+                //   {
+                //     let result = match ::std::iter::IntoIterator::into_iter(<head>) {
+                //       mut iter => {
+                //         [opt_ident]: loop {
+                //           match ::std::iter::Iterator::next(&mut iter) {
+                //             ::std::option::Option::Some(<pat>) => <body>,
+                //             ::std::option::Option::None => break
+                //           }
+                //         }
+                //       }
+                //     };
+                //     result
+                //   }
+
+                let _old_cached = CachedIdSetter::new(lctx, e.id);
+
+                // expand <head>
+                let head = lower_expr(lctx, head);
+
+                let iter = lctx.str_to_ident("iter");
+
+                // `::std::option::Option::Some(<pat>) => <body>`
+                let pat_arm = {
+                    let body_block = lower_block(lctx, body);
+                    let body_span = body_block.span;
+                    let body_expr = P(hir::Expr {
+                        id: lctx.next_id(),
+                        node: hir::ExprBlock(body_block),
+                        span: body_span,
+                    });
+                    let pat = lower_pat(lctx, pat);
+                    let some_pat = pat_some(lctx, e.span, pat);
+
+                    arm(vec![some_pat], body_expr)
+                };
+
+                // `::std::option::Option::None => break`
+                let break_arm = {
+                    let break_expr = expr_break(lctx, e.span);
+
+                    arm(vec![pat_none(lctx, e.span)], break_expr)
+                };
+
+                // `match ::std::iter::Iterator::next(&mut iter) { ... }`
+                let match_expr = {
+                    let next_path = {
+                        let strs = std_path(lctx, &["iter", "Iterator", "next"]);
+
+                        path_global(e.span, strs)
+                    };
+                    let ref_mut_iter = expr_mut_addr_of(lctx,
+                                                        e.span,
+                                                        expr_ident(lctx, e.span, iter));
+                    let next_expr = expr_call(lctx,
+                                              e.span,
+                                              expr_path(lctx, next_path),
+                                              vec![ref_mut_iter]);
+                    let arms = vec![pat_arm, break_arm];
+
+                    expr(lctx,
+                         e.span,
+                         hir::ExprMatch(next_expr, arms, hir::MatchSource::ForLoopDesugar))
+                };
+
+                // `[opt_ident]: loop { ... }`
+                let loop_block = block_expr(lctx, match_expr);
+                let loop_expr = expr(lctx, e.span, hir::ExprLoop(loop_block, opt_ident));
+
+                // `mut iter => { ... }`
+                let iter_arm = {
+                    let iter_pat = pat_ident_binding_mode(lctx,
+                                                          e.span,
+                                                          iter,
+                                                          hir::BindByValue(hir::MutMutable));
+                    arm(vec![iter_pat], loop_expr)
+                };
+
+                // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
+                let into_iter_expr = {
+                    let into_iter_path = {
+                        let strs = std_path(lctx, &["iter", "IntoIterator", "into_iter"]);
+
+                        path_global(e.span, strs)
+                    };
+
+                    expr_call(lctx,
+                              e.span,
+                              expr_path(lctx, into_iter_path),
+                              vec![head])
+                };
+
+                let match_expr = expr_match(lctx,
+                                            e.span,
+                                            into_iter_expr,
+                                            vec![iter_arm],
+                                            hir::MatchSource::ForLoopDesugar);
+
+                // `{ let result = ...; result }`
+                let result_ident = lctx.str_to_ident("result");
+                return expr_block(lctx,
+                                  block_all(lctx,
+                                            e.span,
+                                            vec![stmt_let(lctx,
+                                                          e.span,
+                                                          false,
+                                                          result_ident,
+                                                          match_expr)],
+                                            Some(expr_ident(lctx, e.span, result_ident))))
+            }
+
+            ExprMac(_) => panic!("Shouldn't exist here"),
+        },
+        span: e.span,
+    })
+}
+
+pub fn lower_stmt(_lctx: &LoweringContext, s: &Stmt) -> P<hir::Stmt> {
     match s.node {
         StmtDecl(ref d, id) => {
             P(Spanned {
-                node: hir::StmtDecl(lower_decl(d), id),
-                span: s.span
+                node: hir::StmtDecl(lower_decl(_lctx, d), id),
+                span: s.span,
             })
         }
         StmtExpr(ref e, id) => {
             P(Spanned {
-                node: hir::StmtExpr(lower_expr(e), id),
-                span: s.span
+                node: hir::StmtExpr(lower_expr(_lctx, e), id),
+                span: s.span,
             })
         }
         StmtSemi(ref e, id) => {
             P(Spanned {
-                node: hir::StmtSemi(lower_expr(e), id),
-                span: s.span
+                node: hir::StmtSemi(lower_expr(_lctx, e), id),
+                span: s.span,
             })
         }
-        StmtMac(..) => panic!("Shouldn't exist here")
-    }
-}
-
-pub fn lower_string_style(s: StrStyle) -> hir::StrStyle {
-    match s {
-        CookedStr => hir::CookedStr,
-        RawStr(u) => hir::RawStr(u),
-    }
-}
-
-pub fn unlower_string_style(s: hir::StrStyle) -> StrStyle {
-    match s {
-        hir::CookedStr => CookedStr,
-        hir::RawStr(u) => RawStr(u),
-    }
-}
-
-pub fn lower_match_source(m: &MatchSource) -> hir::MatchSource {
-    match *m {
-        MatchSource::Normal => hir::MatchSource::Normal,
-        MatchSource::IfLetDesugar { contains_else_clause } => {
-            hir::MatchSource::IfLetDesugar { contains_else_clause: contains_else_clause }
-        }
-        MatchSource::WhileLetDesugar => hir::MatchSource::WhileLetDesugar,
-        MatchSource::ForLoopDesugar => hir::MatchSource::ForLoopDesugar,
+        StmtMac(..) => panic!("Shouldn't exist here"),
     }
 }
 
-pub fn lower_capture_clause(c: CaptureClause) -> hir::CaptureClause {
+pub fn lower_capture_clause(_lctx: &LoweringContext, c: CaptureClause) -> hir::CaptureClause {
     match c {
         CaptureByValue => hir::CaptureByValue,
         CaptureByRef => hir::CaptureByRef,
     }
 }
 
-pub fn lower_asm_dialect(a: AsmDialect) -> hir::AsmDialect {
-    match a {
-        AsmAtt => hir::AsmAtt,
-        AsmIntel => hir::AsmIntel,
-    }
-}
-
-pub fn lower_visibility(v: Visibility) -> hir::Visibility {
+pub fn lower_visibility(_lctx: &LoweringContext, v: Visibility) -> hir::Visibility {
     match v {
         Public => hir::Public,
         Inherited => hir::Inherited,
     }
 }
 
-pub fn lower_block_check_mode(b: &BlockCheckMode) -> hir::BlockCheckMode {
+pub fn lower_block_check_mode(_lctx: &LoweringContext, b: &BlockCheckMode) -> hir::BlockCheckMode {
     match *b {
         DefaultBlock => hir::DefaultBlock,
-        UnsafeBlock(u) => hir::UnsafeBlock(lower_unsafe_source(u)),
-        PushUnsafeBlock(u) => hir::PushUnsafeBlock(lower_unsafe_source(u)),
-        PopUnsafeBlock(u) => hir::PopUnsafeBlock(lower_unsafe_source(u)),
+        UnsafeBlock(u) => hir::UnsafeBlock(lower_unsafe_source(_lctx, u)),
     }
 }
 
-pub fn lower_pat_wild_kind(p: PatWildKind) -> hir::PatWildKind {
+pub fn lower_pat_wild_kind(_lctx: &LoweringContext, p: PatWildKind) -> hir::PatWildKind {
     match p {
         PatWildSingle => hir::PatWildSingle,
         PatWildMulti => hir::PatWildMulti,
     }
 }
 
-pub fn lower_binding_mode(b: &BindingMode) -> hir::BindingMode {
+pub fn lower_binding_mode(_lctx: &LoweringContext, b: &BindingMode) -> hir::BindingMode {
     match *b {
-        BindByRef(m) => hir::BindByRef(lower_mutability(m)),
-        BindByValue(m) => hir::BindByValue(lower_mutability(m)),
+        BindByRef(m) => hir::BindByRef(lower_mutability(_lctx, m)),
+        BindByValue(m) => hir::BindByValue(lower_mutability(_lctx, m)),
     }
 }
 
-pub fn lower_struct_field_kind(s: &StructFieldKind) -> hir::StructFieldKind {
+pub fn lower_struct_field_kind(_lctx: &LoweringContext,
+                               s: &StructFieldKind)
+                               -> hir::StructFieldKind {
     match *s {
-        NamedField(ident, vis) => hir::NamedField(ident, lower_visibility(vis)),
-        UnnamedField(vis) => hir::UnnamedField(lower_visibility(vis)),
+        NamedField(ident, vis) => hir::NamedField(ident.name, lower_visibility(_lctx, vis)),
+        UnnamedField(vis) => hir::UnnamedField(lower_visibility(_lctx, vis)),
     }
 }
 
-pub fn lower_unsafe_source(u: UnsafeSource) -> hir::UnsafeSource {
+pub fn lower_unsafe_source(_lctx: &LoweringContext, u: UnsafeSource) -> hir::UnsafeSource {
     match u {
         CompilerGenerated => hir::CompilerGenerated,
         UserProvided => hir::UserProvided,
     }
 }
 
-pub fn lower_impl_polarity(i: ImplPolarity) -> hir::ImplPolarity {
+pub fn lower_impl_polarity(_lctx: &LoweringContext, i: ImplPolarity) -> hir::ImplPolarity {
     match i {
         ImplPolarity::Positive => hir::ImplPolarity::Positive,
         ImplPolarity::Negative => hir::ImplPolarity::Negative,
     }
 }
 
-pub fn lower_float_ty(f: FloatTy) -> hir::FloatTy {
+pub fn lower_trait_bound_modifier(_lctx: &LoweringContext,
+                                  f: TraitBoundModifier)
+                                  -> hir::TraitBoundModifier {
     match f {
-        TyF32 => hir::TyF32,
-        TyF64 => hir::TyF64,
+        TraitBoundModifier::None => hir::TraitBoundModifier::None,
+        TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe,
     }
 }
 
-pub fn unlower_float_ty(f: hir::FloatTy) -> FloatTy {
-    match f {
-        hir::TyF32 => TyF32,
-        hir::TyF64 => TyF64,
+// Helper methods for building HIR.
+
+fn arm(pats: Vec<P<hir::Pat>>, expr: P<hir::Expr>) -> hir::Arm {
+    hir::Arm {
+        attrs: vec!(),
+        pats: pats,
+        guard: None,
+        body: expr,
     }
 }
 
-pub fn lower_lit_int_type(i: &LitIntType) -> hir::LitIntType {
-    match *i {
-        SignedIntLit(i, s) => hir::SignedIntLit(lower_int_ty(i), lower_sign(s)),
-        UnsignedIntLit(u) => hir::UnsignedIntLit(lower_uint_ty(u)),
-        UnsuffixedIntLit(s) => hir::UnsuffixedIntLit(lower_sign(s)),
-    }
+fn expr_break(lctx: &LoweringContext, span: Span) -> P<hir::Expr> {
+    expr(lctx, span, hir::ExprBreak(None))
 }
 
-pub fn unlower_lit_int_type(i: &hir::LitIntType) -> LitIntType {
-    match *i {
-        hir::SignedIntLit(i, s) => SignedIntLit(unlower_int_ty(i), unlower_sign(s)),
-        hir::UnsignedIntLit(u) => UnsignedIntLit(unlower_uint_ty(u)),
-        hir::UnsuffixedIntLit(s) => UnsuffixedIntLit(unlower_sign(s)),
-    }
+fn expr_call(lctx: &LoweringContext,
+             span: Span,
+             e: P<hir::Expr>,
+             args: Vec<P<hir::Expr>>)
+             -> P<hir::Expr> {
+    expr(lctx, span, hir::ExprCall(e, args))
 }
 
-pub fn lower_int_ty(i: IntTy) -> hir::IntTy {
-    match i {
-        TyIs => hir::TyIs,
-        TyI8 => hir::TyI8,
-        TyI16 => hir::TyI16,
-        TyI32 => hir::TyI32,
-        TyI64 => hir::TyI64,
-    }
+fn expr_ident(lctx: &LoweringContext, span: Span, id: Ident) -> P<hir::Expr> {
+    expr_path(lctx, path_ident(span, id))
 }
 
-pub fn unlower_int_ty(i: hir::IntTy) -> IntTy {
-    match i {
-        hir::TyIs => TyIs,
-        hir::TyI8 => TyI8,
-        hir::TyI16 => TyI16,
-        hir::TyI32 => TyI32,
-        hir::TyI64 => TyI64,
-    }
+fn expr_mut_addr_of(lctx: &LoweringContext, span: Span, e: P<hir::Expr>) -> P<hir::Expr> {
+    expr(lctx, span, hir::ExprAddrOf(hir::MutMutable, e))
 }
 
-pub fn lower_uint_ty(u: UintTy) -> hir::UintTy {
-    match u {
-        TyUs => hir::TyUs,
-        TyU8 => hir::TyU8,
-        TyU16 => hir::TyU16,
-        TyU32 => hir::TyU32,
-        TyU64 => hir::TyU64,
-    }
+fn expr_path(lctx: &LoweringContext, path: hir::Path) -> P<hir::Expr> {
+    expr(lctx, path.span, hir::ExprPath(None, path))
 }
 
-pub fn unlower_uint_ty(u: hir::UintTy) -> UintTy {
-    match u {
-        hir::TyUs => TyUs,
-        hir::TyU8 => TyU8,
-        hir::TyU16 => TyU16,
-        hir::TyU32 => TyU32,
-        hir::TyU64 => TyU64,
-    }
+fn expr_match(lctx: &LoweringContext,
+              span: Span,
+              arg: P<hir::Expr>,
+              arms: Vec<hir::Arm>,
+              source: hir::MatchSource)
+              -> P<hir::Expr> {
+    expr(lctx,
+         span,
+         hir::ExprMatch(arg, arms, source))
 }
 
-pub fn lower_sign(f: Sign) -> hir::Sign {
-    match f {
-        Minus => hir::Minus,
-        Plus => hir::Plus,
-    }
+fn expr_block(lctx: &LoweringContext, b: P<hir::Block>) -> P<hir::Expr> {
+    expr(lctx, b.span, hir::ExprBlock(b))
 }
 
-pub fn unlower_sign(f: hir::Sign) -> Sign {
-    match f {
-        hir::Minus => Minus,
-        hir::Plus => Plus,
-    }
+fn expr_tuple(lctx: &LoweringContext, sp: Span, exprs: Vec<P<hir::Expr>>) -> P<hir::Expr> {
+    expr(lctx, sp, hir::ExprTup(exprs))
 }
 
-pub fn lower_trait_bound_modifier(f: TraitBoundModifier) -> hir::TraitBoundModifier {
-    match f {
-        TraitBoundModifier::None => hir::TraitBoundModifier::None,
-        TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe,
+fn expr(lctx: &LoweringContext, span: Span, node: hir::Expr_) -> P<hir::Expr> {
+    P(hir::Expr {
+        id: lctx.next_id(),
+        node: node,
+        span: span,
+    })
+}
+
+fn stmt_let(lctx: &LoweringContext,
+            sp: Span,
+            mutbl: bool,
+            ident: Ident,
+            ex: P<hir::Expr>)
+            -> P<hir::Stmt> {
+    let pat = if mutbl {
+        pat_ident_binding_mode(lctx, sp, ident, hir::BindByValue(hir::MutMutable))
+    } else {
+        pat_ident(lctx, sp, ident)
+    };
+    let local = P(hir::Local {
+        pat: pat,
+        ty: None,
+        init: Some(ex),
+        id: lctx.next_id(),
+        span: sp,
+    });
+    let decl = respan(sp, hir::DeclLocal(local));
+    P(respan(sp, hir::StmtDecl(P(decl), lctx.next_id())))
+}
+
+fn block_expr(lctx: &LoweringContext, expr: P<hir::Expr>) -> P<hir::Block> {
+    block_all(lctx, expr.span, Vec::new(), Some(expr))
+}
+
+fn block_all(lctx: &LoweringContext,
+             span: Span,
+             stmts: Vec<P<hir::Stmt>>,
+             expr: Option<P<hir::Expr>>)
+             -> P<hir::Block> {
+    P(hir::Block {
+        stmts: stmts,
+        expr: expr,
+        id: lctx.next_id(),
+        rules: hir::DefaultBlock,
+        span: span,
+    })
+}
+
+fn pat_some(lctx: &LoweringContext, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
+    let some = std_path(lctx, &["option", "Option", "Some"]);
+    let path = path_global(span, some);
+    pat_enum(lctx, span, path, vec!(pat))
+}
+
+fn pat_none(lctx: &LoweringContext, span: Span) -> P<hir::Pat> {
+    let none = std_path(lctx, &["option", "Option", "None"]);
+    let path = path_global(span, none);
+    pat_enum(lctx, span, path, vec![])
+}
+
+fn pat_enum(lctx: &LoweringContext,
+            span: Span,
+            path: hir::Path,
+            subpats: Vec<P<hir::Pat>>)
+            -> P<hir::Pat> {
+    let pt = hir::PatEnum(path, Some(subpats));
+    pat(lctx, span, pt)
+}
+
+fn pat_ident(lctx: &LoweringContext, span: Span, ident: Ident) -> P<hir::Pat> {
+    pat_ident_binding_mode(lctx, span, ident, hir::BindByValue(hir::MutImmutable))
+}
+
+fn pat_ident_binding_mode(lctx: &LoweringContext,
+                          span: Span,
+                          ident: Ident,
+                          bm: hir::BindingMode)
+                          -> P<hir::Pat> {
+    let pat_ident = hir::PatIdent(bm,
+                                  Spanned {
+                                      span: span,
+                                      node: ident,
+                                  },
+                                  None);
+    pat(lctx, span, pat_ident)
+}
+
+fn pat_wild(lctx: &LoweringContext, span: Span) -> P<hir::Pat> {
+    pat(lctx, span, hir::PatWild(hir::PatWildSingle))
+}
+
+fn pat(lctx: &LoweringContext, span: Span, pat: hir::Pat_) -> P<hir::Pat> {
+    P(hir::Pat {
+        id: lctx.next_id(),
+        node: pat,
+        span: span,
+    })
+}
+
+fn path_ident(span: Span, id: Ident) -> hir::Path {
+    path(span, vec!(id))
+}
+
+fn path(span: Span, strs: Vec<Ident>) -> hir::Path {
+    path_all(span, false, strs, Vec::new(), Vec::new(), Vec::new())
+}
+
+fn path_global(span: Span, strs: Vec<Ident>) -> hir::Path {
+    path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new())
+}
+
+fn path_all(sp: Span,
+            global: bool,
+            mut idents: Vec<Ident>,
+            lifetimes: Vec<hir::Lifetime>,
+            types: Vec<P<hir::Ty>>,
+            bindings: Vec<P<hir::TypeBinding>>)
+            -> hir::Path {
+    let last_identifier = idents.pop().unwrap();
+    let mut segments: Vec<hir::PathSegment> = idents.into_iter()
+                                                    .map(|ident| {
+                                                        hir::PathSegment {
+                                                            identifier: ident,
+                                                            parameters: hir::PathParameters::none(),
+                                                        }
+                                                    })
+                                                    .collect();
+    segments.push(hir::PathSegment {
+        identifier: last_identifier,
+        parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
+            lifetimes: lifetimes,
+            types: OwnedSlice::from_vec(types),
+            bindings: OwnedSlice::from_vec(bindings),
+        }),
+    });
+    hir::Path {
+        span: sp,
+        global: global,
+        segments: segments,
     }
 }
 
-pub fn lower_attr_style(f: AttrStyle) -> hir::AttrStyle {
-    match f {
-        AttrOuter => hir::AttrOuter,
-        AttrInner => hir::AttrInner,
+fn std_path(lctx: &LoweringContext, components: &[&str]) -> Vec<Ident> {
+    let mut v = Vec::new();
+    if let Some(s) = lctx.crate_root {
+        v.push(str_to_ident(s));
     }
+    v.extend(components.iter().map(|s| str_to_ident(s)));
+    return v
 }
 
-pub fn unlower_attr_style(f: hir::AttrStyle) -> AttrStyle {
-    match f {
-        hir::AttrOuter => AttrOuter,
-        hir::AttrInner => AttrInner,
+// Given suffix ["b","c","d"], returns path `::std::b::c::d` when
+// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
+fn core_path(lctx: &LoweringContext, span: Span, components: &[&str]) -> hir::Path {
+    let idents = std_path(lctx, components);
+    path_global(span, idents)
+}
+
+fn signal_block_expr(lctx: &LoweringContext,
+                     stmts: Vec<P<hir::Stmt>>,
+                     expr: P<hir::Expr>,
+                     span: Span,
+                     rule: hir::BlockCheckMode)
+                     -> P<hir::Expr> {
+    expr_block(lctx,
+               P(hir::Block {
+                   rules: rule,
+                   span: span,
+                   id: lctx.next_id(),
+                   stmts: stmts,
+                   expr: Some(expr),
+               }))
+}
+
+
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use syntax::ast::{self, NodeId, NodeIdAssigner};
+    use syntax::{parse, codemap};
+    use syntax::fold::Folder;
+    use std::cell::Cell;
+
+    struct MockAssigner {
+        next_id: Cell<NodeId>,
+    }
+
+    impl MockAssigner {
+        fn new() -> MockAssigner {
+            MockAssigner {
+                next_id: Cell::new(0),
+            }
+        }
+    }
+
+    trait FakeExtCtxt {
+        fn call_site(&self) -> codemap::Span;
+        fn cfg(&self) -> ast::CrateConfig;
+        fn ident_of(&self, st: &str) -> ast::Ident;
+        fn name_of(&self, st: &str) -> ast::Name;
+        fn parse_sess(&self) -> &parse::ParseSess;
+    }
+
+    impl FakeExtCtxt for parse::ParseSess {
+        fn call_site(&self) -> codemap::Span {
+            codemap::Span {
+                lo: codemap::BytePos(0),
+                hi: codemap::BytePos(0),
+                expn_id: codemap::NO_EXPANSION,
+            }
+        }
+        fn cfg(&self) -> ast::CrateConfig { Vec::new() }
+        fn ident_of(&self, st: &str) -> ast::Ident {
+            parse::token::str_to_ident(st)
+        }
+        fn name_of(&self, st: &str) -> ast::Name {
+            parse::token::intern(st)
+        }
+        fn parse_sess(&self) -> &parse::ParseSess { self }
+    }
+
+    impl NodeIdAssigner for MockAssigner {
+        fn next_node_id(&self) -> NodeId {
+            let result = self.next_id.get();
+            self.next_id.set(result + 1);
+            result
+        }
+
+        fn peek_node_id(&self) -> NodeId {
+            self.next_id.get()
+        }
+    }
+
+    impl Folder for MockAssigner {
+        fn new_id(&mut self, old_id: NodeId) -> NodeId {
+            assert_eq!(old_id, ast::DUMMY_NODE_ID);
+            self.next_node_id()
+        }
+    }
+
+    #[test]
+    fn test_preserves_ids() {
+        let cx = parse::ParseSess::new();
+        let mut assigner = MockAssigner::new();
+
+        let ast_if_let = quote_expr!(&cx, if let Some(foo) = baz { bar(foo); });
+        let ast_if_let = assigner.fold_expr(ast_if_let);
+        let ast_while_let = quote_expr!(&cx, while let Some(foo) = baz { bar(foo); });
+        let ast_while_let = assigner.fold_expr(ast_while_let);
+        let ast_for = quote_expr!(&cx, for i in 0..10 { foo(i); });
+        let ast_for = assigner.fold_expr(ast_for);
+        let ast_in = quote_expr!(&cx, in HEAP { foo() });
+        let ast_in = assigner.fold_expr(ast_in);
+
+        let lctx = LoweringContext::new(&assigner, None);
+        let hir1 = lower_expr(&lctx, &ast_if_let);
+        let hir2 = lower_expr(&lctx, &ast_if_let);
+        assert!(hir1 == hir2);
+
+        let hir1 = lower_expr(&lctx, &ast_while_let);
+        let hir2 = lower_expr(&lctx, &ast_while_let);
+        assert!(hir1 == hir2);
+
+        let hir1 = lower_expr(&lctx, &ast_for);
+        let hir2 = lower_expr(&lctx, &ast_for);
+        assert!(hir1 == hir2);
+
+        let hir1 = lower_expr(&lctx, &ast_in);
+        let hir2 = lower_expr(&lctx, &ast_in);
+        assert!(hir1 == hir2);
     }
 }
diff --git a/src/librustc_front/print/pp.rs b/src/librustc_front/print/pp.rs
deleted file mode 100644 (file)
index 7c5a464..0000000
+++ /dev/null
@@ -1,686 +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.
-
-//! This pretty-printer is a direct reimplementation of Philip Karlton's
-//! Mesa pretty-printer, as described in appendix A of
-//!
-//!     STAN-CS-79-770: "Pretty Printing", by Derek C. Oppen.
-//!     Stanford Department of Computer Science, 1979.
-//!
-//! The algorithm's aim is to break a stream into as few lines as possible
-//! while respecting the indentation-consistency requirements of the enclosing
-//! block, and avoiding breaking at silly places on block boundaries, for
-//! example, between "x" and ")" in "x)".
-//!
-//! I am implementing this algorithm because it comes with 20 pages of
-//! documentation explaining its theory, and because it addresses the set of
-//! concerns I've seen other pretty-printers fall down on. Weirdly. Even though
-//! it's 32 years old. What can I say?
-//!
-//! Despite some redundancies and quirks in the way it's implemented in that
-//! paper, I've opted to keep the implementation here as similar as I can,
-//! changing only what was blatantly wrong, a typo, or sufficiently
-//! non-idiomatic rust that it really stuck out.
-//!
-//! In particular you'll see a certain amount of churn related to INTEGER vs.
-//! CARDINAL in the Mesa implementation. Mesa apparently interconverts the two
-//! somewhat readily? In any case, I've used usize for indices-in-buffers and
-//! ints for character-sizes-and-indentation-offsets. This respects the need
-//! for ints to "go negative" while carrying a pending-calculation balance, and
-//! helps differentiate all the numbers flying around internally (slightly).
-//!
-//! I also inverted the indentation arithmetic used in the print stack, since
-//! the Mesa implementation (somewhat randomly) stores the offset on the print
-//! stack in terms of margin-col rather than col itself. I store col.
-//!
-//! I also implemented a small change in the String token, in that I store an
-//! explicit length for the string. For most tokens this is just the length of
-//! the accompanying string. But it's necessary to permit it to differ, for
-//! encoding things that are supposed to "go on their own line" -- certain
-//! classes of comment and blank-line -- where relying on adjacent
-//! hardbreak-like Break tokens with long blankness indication doesn't actually
-//! work. To see why, consider when there is a "thing that should be on its own
-//! line" between two long blocks, say functions. If you put a hardbreak after
-//! each function (or before each) and the breaking algorithm decides to break
-//! there anyways (because the functions themselves are long) you wind up with
-//! extra blank lines. If you don't put hardbreaks you can wind up with the
-//! "thing which should be on its own line" not getting its own line in the
-//! rare case of "really small functions" or such. This re-occurs with comments
-//! and explicit blank lines. So in those cases we use a string with a payload
-//! we want isolated to a line and an explicit length that's huge, surrounded
-//! by two zero-length breaks. The algorithm will try its best to fit it on a
-//! line (which it can't) and so naturally place the content on its own line to
-//! avoid combining it with other lines and making matters even worse.
-
-use std::io;
-use std::string;
-
-#[derive(Clone, Copy, PartialEq)]
-pub enum Breaks {
-    Consistent,
-    Inconsistent,
-}
-
-#[derive(Clone, Copy)]
-pub struct BreakToken {
-    offset: isize,
-    blank_space: isize
-}
-
-#[derive(Clone, Copy)]
-pub struct BeginToken {
-    offset: isize,
-    breaks: Breaks
-}
-
-#[derive(Clone)]
-pub enum Token {
-    String(String, isize),
-    Break(BreakToken),
-    Begin(BeginToken),
-    End,
-    Eof,
-}
-
-impl Token {
-    pub fn is_eof(&self) -> bool {
-        match *self {
-            Token::Eof => true,
-            _ => false,
-        }
-    }
-
-    pub fn is_hardbreak_tok(&self) -> bool {
-        match *self {
-            Token::Break(BreakToken {
-                offset: 0,
-                blank_space: bs
-            }) if bs == SIZE_INFINITY =>
-                true,
-            _ =>
-                false
-        }
-    }
-}
-
-pub fn tok_str(token: &Token) -> String {
-    match *token {
-        Token::String(ref s, len) => format!("STR({},{})", s, len),
-        Token::Break(_) => "BREAK".to_string(),
-        Token::Begin(_) => "BEGIN".to_string(),
-        Token::End => "END".to_string(),
-        Token::Eof => "EOF".to_string()
-    }
-}
-
-pub fn buf_str(toks: &[Token],
-               szs: &[isize],
-               left: usize,
-               right: usize,
-               lim: usize)
-               -> String {
-    let n = toks.len();
-    assert_eq!(n, szs.len());
-    let mut i = left;
-    let mut l = lim;
-    let mut s = string::String::from("[");
-    while i != right && l != 0 {
-        l -= 1;
-        if i != left {
-            s.push_str(", ");
-        }
-        s.push_str(&format!("{}={}",
-                           szs[i],
-                           tok_str(&toks[i])));
-        i += 1;
-        i %= n;
-    }
-    s.push(']');
-    s
-}
-
-#[derive(Copy, Clone)]
-pub enum PrintStackBreak {
-    Fits,
-    Broken(Breaks),
-}
-
-#[derive(Copy, Clone)]
-pub struct PrintStackElem {
-    offset: isize,
-    pbreak: PrintStackBreak
-}
-
-const SIZE_INFINITY: isize = 0xffff;
-
-pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> {
-    // Yes 3, it makes the ring buffers big enough to never
-    // fall behind.
-    let n: usize = 3 * linewidth;
-    debug!("mk_printer {}", linewidth);
-    let token = vec![Token::Eof; n];
-    let size = vec![0_isize; n];
-    let scan_stack = vec![0_usize; n];
-    Printer {
-        out: out,
-        buf_len: n,
-        margin: linewidth as isize,
-        space: linewidth as isize,
-        left: 0,
-        right: 0,
-        token: token,
-        size: size,
-        left_total: 0,
-        right_total: 0,
-        scan_stack: scan_stack,
-        scan_stack_empty: true,
-        top: 0,
-        bottom: 0,
-        print_stack: Vec::new(),
-        pending_indentation: 0
-    }
-}
-
-
-/// In case you do not have the paper, here is an explanation of what's going
-/// on.
-///
-/// There is a stream of input tokens flowing through this printer.
-///
-/// The printer buffers up to 3N tokens inside itself, where N is linewidth.
-/// Yes, linewidth is chars and tokens are multi-char, but in the worst
-/// case every token worth buffering is 1 char long, so it's ok.
-///
-/// Tokens are String, Break, and Begin/End to delimit blocks.
-///
-/// Begin tokens can carry an offset, saying "how far to indent when you break
-/// inside here", as well as a flag indicating "consistent" or "inconsistent"
-/// breaking. Consistent breaking means that after the first break, no attempt
-/// will be made to flow subsequent breaks together onto lines. Inconsistent
-/// is the opposite. Inconsistent breaking example would be, say:
-///
-///  foo(hello, there, good, friends)
-///
-/// breaking inconsistently to become
-///
-///  foo(hello, there
-///      good, friends);
-///
-/// whereas a consistent breaking would yield:
-///
-///  foo(hello,
-///      there
-///      good,
-///      friends);
-///
-/// That is, in the consistent-break blocks we value vertical alignment
-/// more than the ability to cram stuff onto a line. But in all cases if it
-/// can make a block a one-liner, it'll do so.
-///
-/// Carrying on with high-level logic:
-///
-/// The buffered tokens go through a ring-buffer, 'tokens'. The 'left' and
-/// 'right' indices denote the active portion of the ring buffer as well as
-/// describing hypothetical points-in-the-infinite-stream at most 3N tokens
-/// apart (i.e. "not wrapped to ring-buffer boundaries"). The paper will switch
-/// between using 'left' and 'right' terms to denote the wrapped-to-ring-buffer
-/// and point-in-infinite-stream senses freely.
-///
-/// There is a parallel ring buffer, 'size', that holds the calculated size of
-/// each token. Why calculated? Because for Begin/End pairs, the "size"
-/// includes everything between the pair. That is, the "size" of Begin is
-/// actually the sum of the sizes of everything between Begin and the paired
-/// End that follows. Since that is arbitrarily far in the future, 'size' is
-/// being rewritten regularly while the printer runs; in fact most of the
-/// machinery is here to work out 'size' entries on the fly (and give up when
-/// they're so obviously over-long that "infinity" is a good enough
-/// approximation for purposes of line breaking).
-///
-/// The "input side" of the printer is managed as an abstract process called
-/// SCAN, which uses 'scan_stack', 'scan_stack_empty', 'top' and 'bottom', to
-/// manage calculating 'size'. SCAN is, in other words, the process of
-/// calculating 'size' entries.
-///
-/// The "output side" of the printer is managed by an abstract process called
-/// PRINT, which uses 'print_stack', 'margin' and 'space' to figure out what to
-/// do with each token/size pair it consumes as it goes. It's trying to consume
-/// the entire buffered window, but can't output anything until the size is >=
-/// 0 (sizes are set to negative while they're pending calculation).
-///
-/// So SCAN takes input and buffers tokens and pending calculations, while
-/// PRINT gobbles up completed calculations and tokens from the buffer. The
-/// theory is that the two can never get more than 3N tokens apart, because
-/// once there's "obviously" too much data to fit on a line, in a size
-/// calculation, SCAN will write "infinity" to the size and let PRINT consume
-/// it.
-///
-/// In this implementation (following the paper, again) the SCAN process is
-/// the method called 'pretty_print', and the 'PRINT' process is the method
-/// called 'print'.
-pub struct Printer<'a> {
-    pub out: Box<io::Write+'a>,
-    buf_len: usize,
-    /// Width of lines we're constrained to
-    margin: isize,
-    /// Number of spaces left on line
-    space: isize,
-    /// Index of left side of input stream
-    left: usize,
-    /// Index of right side of input stream
-    right: usize,
-    /// Ring-buffer stream goes through
-    token: Vec<Token> ,
-    /// Ring-buffer of calculated sizes
-    size: Vec<isize> ,
-    /// Running size of stream "...left"
-    left_total: isize,
-    /// Running size of stream "...right"
-    right_total: isize,
-    /// Pseudo-stack, really a ring too. Holds the
-    /// primary-ring-buffers index of the Begin that started the
-    /// current block, possibly with the most recent Break after that
-    /// Begin (if there is any) on top of it. Stuff is flushed off the
-    /// bottom as it becomes irrelevant due to the primary ring-buffer
-    /// advancing.
-    scan_stack: Vec<usize> ,
-    /// Top==bottom disambiguator
-    scan_stack_empty: bool,
-    /// Index of top of scan_stack
-    top: usize,
-    /// Index of bottom of scan_stack
-    bottom: usize,
-    /// Stack of blocks-in-progress being flushed by print
-    print_stack: Vec<PrintStackElem> ,
-    /// Buffered indentation to avoid writing trailing whitespace
-    pending_indentation: isize,
-}
-
-impl<'a> Printer<'a> {
-    pub fn last_token(&mut self) -> Token {
-        self.token[self.right].clone()
-    }
-    // be very careful with this!
-    pub fn replace_last_token(&mut self, t: Token) {
-        self.token[self.right] = t;
-    }
-    pub fn pretty_print(&mut self, token: Token) -> io::Result<()> {
-        debug!("pp Vec<{},{}>", self.left, self.right);
-        match token {
-          Token::Eof => {
-            if !self.scan_stack_empty {
-                self.check_stack(0);
-                try!(self.advance_left());
-            }
-            self.indent(0);
-            Ok(())
-          }
-          Token::Begin(b) => {
-            if self.scan_stack_empty {
-                self.left_total = 1;
-                self.right_total = 1;
-                self.left = 0;
-                self.right = 0;
-            } else { self.advance_right(); }
-            debug!("pp Begin({})/buffer Vec<{},{}>",
-                   b.offset, self.left, self.right);
-            self.token[self.right] = token;
-            self.size[self.right] = -self.right_total;
-            let right = self.right;
-            self.scan_push(right);
-            Ok(())
-          }
-          Token::End => {
-            if self.scan_stack_empty {
-                debug!("pp End/print Vec<{},{}>", self.left, self.right);
-                self.print(token, 0)
-            } else {
-                debug!("pp End/buffer Vec<{},{}>", self.left, self.right);
-                self.advance_right();
-                self.token[self.right] = token;
-                self.size[self.right] = -1;
-                let right = self.right;
-                self.scan_push(right);
-                Ok(())
-            }
-          }
-          Token::Break(b) => {
-            if self.scan_stack_empty {
-                self.left_total = 1;
-                self.right_total = 1;
-                self.left = 0;
-                self.right = 0;
-            } else { self.advance_right(); }
-            debug!("pp Break({})/buffer Vec<{},{}>",
-                   b.offset, self.left, self.right);
-            self.check_stack(0);
-            let right = self.right;
-            self.scan_push(right);
-            self.token[self.right] = token;
-            self.size[self.right] = -self.right_total;
-            self.right_total += b.blank_space;
-            Ok(())
-          }
-          Token::String(s, len) => {
-            if self.scan_stack_empty {
-                debug!("pp String('{}')/print Vec<{},{}>",
-                       s, self.left, self.right);
-                self.print(Token::String(s, len), len)
-            } else {
-                debug!("pp String('{}')/buffer Vec<{},{}>",
-                       s, self.left, self.right);
-                self.advance_right();
-                self.token[self.right] = Token::String(s, len);
-                self.size[self.right] = len;
-                self.right_total += len;
-                self.check_stream()
-            }
-          }
-        }
-    }
-    pub fn check_stream(&mut self) -> io::Result<()> {
-        debug!("check_stream Vec<{}, {}> with left_total={}, right_total={}",
-               self.left, self.right, self.left_total, self.right_total);
-        if self.right_total - self.left_total > self.space {
-            debug!("scan window is {}, longer than space on line ({})",
-                   self.right_total - self.left_total, self.space);
-            if !self.scan_stack_empty {
-                if self.left == self.scan_stack[self.bottom] {
-                    debug!("setting {} to infinity and popping", self.left);
-                    let scanned = self.scan_pop_bottom();
-                    self.size[scanned] = SIZE_INFINITY;
-                }
-            }
-            try!(self.advance_left());
-            if self.left != self.right {
-                try!(self.check_stream());
-            }
-        }
-        Ok(())
-    }
-    pub fn scan_push(&mut self, x: usize) {
-        debug!("scan_push {}", x);
-        if self.scan_stack_empty {
-            self.scan_stack_empty = false;
-        } else {
-            self.top += 1;
-            self.top %= self.buf_len;
-            assert!((self.top != self.bottom));
-        }
-        self.scan_stack[self.top] = x;
-    }
-    pub fn scan_pop(&mut self) -> usize {
-        assert!((!self.scan_stack_empty));
-        let x = self.scan_stack[self.top];
-        if self.top == self.bottom {
-            self.scan_stack_empty = true;
-        } else {
-            self.top += self.buf_len - 1; self.top %= self.buf_len;
-        }
-        return x;
-    }
-    pub fn scan_top(&mut self) -> usize {
-        assert!((!self.scan_stack_empty));
-        return self.scan_stack[self.top];
-    }
-    pub fn scan_pop_bottom(&mut self) -> usize {
-        assert!((!self.scan_stack_empty));
-        let x = self.scan_stack[self.bottom];
-        if self.top == self.bottom {
-            self.scan_stack_empty = true;
-        } else {
-            self.bottom += 1; self.bottom %= self.buf_len;
-        }
-        return x;
-    }
-    pub fn advance_right(&mut self) {
-        self.right += 1;
-        self.right %= self.buf_len;
-        assert!((self.right != self.left));
-    }
-    pub fn advance_left(&mut self) -> io::Result<()> {
-        debug!("advance_left Vec<{},{}>, sizeof({})={}", self.left, self.right,
-               self.left, self.size[self.left]);
-
-        let mut left_size = self.size[self.left];
-
-        while left_size >= 0 {
-            let left = self.token[self.left].clone();
-
-            let len = match left {
-                Token::Break(b) => b.blank_space,
-                Token::String(_, len) => {
-                    assert_eq!(len, left_size);
-                    len
-                }
-                _ => 0
-            };
-
-            try!(self.print(left, left_size));
-
-            self.left_total += len;
-
-            if self.left == self.right {
-                break;
-            }
-
-            self.left += 1;
-            self.left %= self.buf_len;
-
-            left_size = self.size[self.left];
-        }
-
-        Ok(())
-    }
-    pub fn check_stack(&mut self, k: isize) {
-        if !self.scan_stack_empty {
-            let x = self.scan_top();
-            match self.token[x] {
-                Token::Begin(_) => {
-                    if k > 0 {
-                        let popped = self.scan_pop();
-                        self.size[popped] = self.size[x] + self.right_total;
-                        self.check_stack(k - 1);
-                    }
-                }
-                Token::End => {
-                    // paper says + not =, but that makes no sense.
-                    let popped = self.scan_pop();
-                    self.size[popped] = 1;
-                    self.check_stack(k + 1);
-                }
-                _ => {
-                    let popped = self.scan_pop();
-                    self.size[popped] = self.size[x] + self.right_total;
-                    if k > 0 {
-                        self.check_stack(k);
-                    }
-                }
-            }
-        }
-    }
-    pub fn print_newline(&mut self, amount: isize) -> io::Result<()> {
-        debug!("NEWLINE {}", amount);
-        let ret = write!(self.out, "\n");
-        self.pending_indentation = 0;
-        self.indent(amount);
-        return ret;
-    }
-    pub fn indent(&mut self, amount: isize) {
-        debug!("INDENT {}", amount);
-        self.pending_indentation += amount;
-    }
-    pub fn get_top(&mut self) -> PrintStackElem {
-        let print_stack = &mut self.print_stack;
-        let n = print_stack.len();
-        if n != 0 {
-            (*print_stack)[n - 1]
-        } else {
-            PrintStackElem {
-                offset: 0,
-                pbreak: PrintStackBreak::Broken(Breaks::Inconsistent)
-            }
-        }
-    }
-    pub fn print_str(&mut self, s: &str) -> io::Result<()> {
-        while self.pending_indentation > 0 {
-            try!(write!(self.out, " "));
-            self.pending_indentation -= 1;
-        }
-        write!(self.out, "{}", s)
-    }
-    pub fn print(&mut self, token: Token, l: isize) -> io::Result<()> {
-        debug!("print {} {} (remaining line space={})", tok_str(&token), l,
-               self.space);
-        debug!("{}", buf_str(&self.token,
-                             &self.size,
-                             self.left,
-                             self.right,
-                             6));
-        match token {
-          Token::Begin(b) => {
-            if l > self.space {
-                let col = self.margin - self.space + b.offset;
-                debug!("print Begin -> push broken block at col {}", col);
-                self.print_stack.push(PrintStackElem {
-                    offset: col,
-                    pbreak: PrintStackBreak::Broken(b.breaks)
-                });
-            } else {
-                debug!("print Begin -> push fitting block");
-                self.print_stack.push(PrintStackElem {
-                    offset: 0,
-                    pbreak: PrintStackBreak::Fits
-                });
-            }
-            Ok(())
-          }
-          Token::End => {
-            debug!("print End -> pop End");
-            let print_stack = &mut self.print_stack;
-            assert!((!print_stack.is_empty()));
-            print_stack.pop().unwrap();
-            Ok(())
-          }
-          Token::Break(b) => {
-            let top = self.get_top();
-            match top.pbreak {
-              PrintStackBreak::Fits => {
-                debug!("print Break({}) in fitting block", b.blank_space);
-                self.space -= b.blank_space;
-                self.indent(b.blank_space);
-                Ok(())
-              }
-              PrintStackBreak::Broken(Breaks::Consistent) => {
-                debug!("print Break({}+{}) in consistent block",
-                       top.offset, b.offset);
-                let ret = self.print_newline(top.offset + b.offset);
-                self.space = self.margin - (top.offset + b.offset);
-                ret
-              }
-              PrintStackBreak::Broken(Breaks::Inconsistent) => {
-                if l > self.space {
-                    debug!("print Break({}+{}) w/ newline in inconsistent",
-                           top.offset, b.offset);
-                    let ret = self.print_newline(top.offset + b.offset);
-                    self.space = self.margin - (top.offset + b.offset);
-                    ret
-                } else {
-                    debug!("print Break({}) w/o newline in inconsistent",
-                           b.blank_space);
-                    self.indent(b.blank_space);
-                    self.space -= b.blank_space;
-                    Ok(())
-                }
-              }
-            }
-          }
-          Token::String(s, len) => {
-            debug!("print String({})", s);
-            assert_eq!(l, len);
-            // assert!(l <= space);
-            self.space -= len;
-            self.print_str(&s[..])
-          }
-          Token::Eof => {
-            // Eof should never get here.
-            panic!();
-          }
-        }
-    }
-}
-
-// Convenience functions to talk to the printer.
-//
-// "raw box"
-pub fn rbox(p: &mut Printer, indent: usize, b: Breaks) -> io::Result<()> {
-    p.pretty_print(Token::Begin(BeginToken {
-        offset: indent as isize,
-        breaks: b
-    }))
-}
-
-pub fn ibox(p: &mut Printer, indent: usize) -> io::Result<()> {
-    rbox(p, indent, Breaks::Inconsistent)
-}
-
-pub fn cbox(p: &mut Printer, indent: usize) -> io::Result<()> {
-    rbox(p, indent, Breaks::Consistent)
-}
-
-pub fn break_offset(p: &mut Printer, n: usize, off: isize) -> io::Result<()> {
-    p.pretty_print(Token::Break(BreakToken {
-        offset: off,
-        blank_space: n as isize
-    }))
-}
-
-pub fn end(p: &mut Printer) -> io::Result<()> {
-    p.pretty_print(Token::End)
-}
-
-pub fn eof(p: &mut Printer) -> io::Result<()> {
-    p.pretty_print(Token::Eof)
-}
-
-pub fn word(p: &mut Printer, wrd: &str) -> io::Result<()> {
-    p.pretty_print(Token::String(/* bad */ wrd.to_string(), wrd.len() as isize))
-}
-
-pub fn huge_word(p: &mut Printer, wrd: &str) -> io::Result<()> {
-    p.pretty_print(Token::String(/* bad */ wrd.to_string(), SIZE_INFINITY))
-}
-
-pub fn zero_word(p: &mut Printer, wrd: &str) -> io::Result<()> {
-    p.pretty_print(Token::String(/* bad */ wrd.to_string(), 0))
-}
-
-pub fn spaces(p: &mut Printer, n: usize) -> io::Result<()> {
-    break_offset(p, n, 0)
-}
-
-pub fn zerobreak(p: &mut Printer) -> io::Result<()> {
-    spaces(p, 0)
-}
-
-pub fn space(p: &mut Printer) -> io::Result<()> {
-    spaces(p, 1)
-}
-
-pub fn hardbreak(p: &mut Printer) -> io::Result<()> {
-    spaces(p, SIZE_INFINITY as usize)
-}
-
-pub fn hardbreak_tok_offset(off: isize) -> Token {
-    Token::Break(BreakToken {offset: off, blank_space: SIZE_INFINITY})
-}
-
-pub fn hardbreak_tok() -> Token {
-    hardbreak_tok_offset(0)
-}
index a1382b467fb876fc1545d531b5e0dc71a95497eb..a3a4bede379e9c739c3aa690ac4e1256a237706d 100644 (file)
@@ -13,26 +13,23 @@ pub use self::AnnNode::*;
 use syntax::abi;
 use syntax::ast;
 use syntax::owned_slice::OwnedSlice;
-use syntax::codemap::{self, CodeMap, BytePos};
+use syntax::codemap::{self, CodeMap, BytePos, Spanned};
 use syntax::diagnostic;
 use syntax::parse::token::{self, BinOpToken};
 use syntax::parse::lexer::comments;
 use syntax::parse;
-use syntax::print::pp::{self, break_offset, word, space, zerobreak, hardbreak};
+use syntax::print::pp::{self, break_offset, word, space, hardbreak};
 use syntax::print::pp::{Breaks, eof};
 use syntax::print::pp::Breaks::{Consistent, Inconsistent};
+use syntax::print::pprust::{self as ast_pp, PrintState};
 use syntax::ptr::P;
 
 use hir;
 use hir::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
-use attr::{AttrMetaMethods, AttributeMethods};
 
-use std::ascii;
 use std::io::{self, Write, Read};
-use std::iter;
 
 pub enum AnnNode<'a> {
-    NodeIdent(&'a ast::Ident),
     NodeName(&'a ast::Name),
     NodeBlock(&'a hir::Block),
     NodeItem(&'a hir::Item),
@@ -42,8 +39,12 @@ pub enum AnnNode<'a> {
 }
 
 pub trait PpAnn {
-    fn pre(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { Ok(()) }
-    fn post(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { Ok(()) }
+    fn pre(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> {
+        Ok(())
+    }
+    fn post(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> {
+        Ok(())
+    }
 }
 
 #[derive(Copy, Clone)]
@@ -51,37 +52,53 @@ pub struct NoAnn;
 
 impl PpAnn for NoAnn {}
 
-#[derive(Copy, Clone)]
-pub struct CurrentCommentAndLiteral {
-    cur_cmnt: usize,
-    cur_lit: usize,
-}
 
 pub struct State<'a> {
     pub s: pp::Printer<'a>,
     cm: Option<&'a CodeMap>,
-    comments: Option<Vec<comments::Comment> >,
-    literals: Option<Vec<comments::Literal> >,
-    cur_cmnt_and_lit: CurrentCommentAndLiteral,
+    comments: Option<Vec<comments::Comment>>,
+    literals: Option<Vec<comments::Literal>>,
+    cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral,
     boxes: Vec<pp::Breaks>,
-    ann: &'a (PpAnn+'a),
+    ann: &'a (PpAnn + 'a),
 }
 
-pub fn rust_printer<'a>(writer: Box<Write+'a>) -> State<'a> {
+impl<'a> PrintState<'a> for State<'a> {
+    fn writer(&mut self) -> &mut pp::Printer<'a> {
+        &mut self.s
+    }
+
+    fn boxes(&mut self) -> &mut Vec<pp::Breaks> {
+        &mut self.boxes
+    }
+
+    fn comments(&mut self) -> &mut Option<Vec<comments::Comment>> {
+        &mut self.comments
+    }
+
+    fn cur_cmnt_and_lit(&mut self) -> &mut ast_pp::CurrentCommentAndLiteral {
+        &mut self.cur_cmnt_and_lit
+    }
+
+    fn literals(&self) -> &Option<Vec<comments::Literal>> {
+        &self.literals
+    }
+}
+
+pub fn rust_printer<'a>(writer: Box<Write + 'a>) -> State<'a> {
     static NO_ANN: NoAnn = NoAnn;
     rust_printer_annotated(writer, &NO_ANN)
 }
 
-pub fn rust_printer_annotated<'a>(writer: Box<Write+'a>,
-                                  ann: &'a PpAnn) -> State<'a> {
+pub fn rust_printer_annotated<'a>(writer: Box<Write + 'a>, ann: &'a PpAnn) -> State<'a> {
     State {
         s: pp::mk_printer(writer, default_columns),
         cm: None,
         comments: None,
         literals: None,
-        cur_cmnt_and_lit: CurrentCommentAndLiteral {
+        cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral {
             cur_cmnt: 0,
-            cur_lit: 0
+            cur_lit: 0,
         },
         boxes: Vec::new(),
         ann: ann,
@@ -103,16 +120,11 @@ pub fn print_crate<'a>(cm: &'a CodeMap,
                        krate: &hir::Crate,
                        filename: String,
                        input: &mut Read,
-                       out: Box<Write+'a>,
+                       out: Box<Write + 'a>,
                        ann: &'a PpAnn,
-                       is_expanded: bool) -> io::Result<()> {
-    let mut s = State::new_from_input(cm,
-                                      span_diagnostic,
-                                      filename,
-                                      input,
-                                      out,
-                                      ann,
-                                      is_expanded);
+                       is_expanded: bool)
+                       -> io::Result<()> {
+    let mut s = State::new_from_input(cm, span_diagnostic, filename, input, out, ann, is_expanded);
 
     // When printing the AST, we sometimes need to inject `#[no_std]` here.
     // Since you can't compile the HIR, it's not necessary.
@@ -127,38 +139,42 @@ impl<'a> State<'a> {
                           span_diagnostic: &diagnostic::SpanHandler,
                           filename: String,
                           input: &mut Read,
-                          out: Box<Write+'a>,
+                          out: Box<Write + 'a>,
                           ann: &'a PpAnn,
-                          is_expanded: bool) -> State<'a> {
-        let (cmnts, lits) = comments::gather_comments_and_literals(
-            span_diagnostic,
-            filename,
-            input);
-
-        State::new(
-            cm,
-            out,
-            ann,
-            Some(cmnts),
-            // If the code is post expansion, don't use the table of
-            // literals, since it doesn't correspond with the literals
-            // in the AST anymore.
-            if is_expanded { None } else { Some(lits) })
+                          is_expanded: bool)
+                          -> State<'a> {
+        let (cmnts, lits) = comments::gather_comments_and_literals(span_diagnostic,
+                                                                   filename,
+                                                                   input);
+
+        State::new(cm,
+                   out,
+                   ann,
+                   Some(cmnts),
+                   // If the code is post expansion, don't use the table of
+                   // literals, since it doesn't correspond with the literals
+                   // in the AST anymore.
+                   if is_expanded {
+                       None
+                   } else {
+                       Some(lits)
+                   })
     }
 
     pub fn new(cm: &'a CodeMap,
-               out: Box<Write+'a>,
+               out: Box<Write + 'a>,
                ann: &'a PpAnn,
                comments: Option<Vec<comments::Comment>>,
-               literals: Option<Vec<comments::Literal>>) -> State<'a> {
+               literals: Option<Vec<comments::Literal>>)
+               -> State<'a> {
         State {
             s: pp::mk_printer(out, default_columns),
             cm: Some(cm),
-            comments: comments,
-            literals: literals,
-            cur_cmnt_and_lit: CurrentCommentAndLiteral {
+            comments: comments.clone(),
+            literals: literals.clone(),
+            cur_cmnt_and_lit: ast_pp::CurrentCommentAndLiteral {
                 cur_cmnt: 0,
-                cur_lit: 0
+                cur_lit: 0,
             },
             boxes: Vec::new(),
             ann: ann,
@@ -166,8 +182,8 @@ impl<'a> State<'a> {
     }
 }
 
-pub fn to_string<F>(f: F) -> String where
-    F: FnOnce(&mut State) -> io::Result<()>,
+pub fn to_string<F>(f: F) -> String
+    where F: FnOnce(&mut State) -> io::Result<()>
 {
     let mut wr = Vec::new();
     {
@@ -180,16 +196,16 @@ pub fn to_string<F>(f: F) -> String where
 
 pub fn binop_to_string(op: BinOpToken) -> &'static str {
     match op {
-        token::Plus     => "+",
-        token::Minus    => "-",
-        token::Star     => "*",
-        token::Slash    => "/",
-        token::Percent  => "%",
-        token::Caret    => "^",
-        token::And      => "&",
-        token::Or       => "|",
-        token::Shl      => "<<",
-        token::Shr      => ">>",
+        token::Plus => "+",
+        token::Minus => "-",
+        token::Star => "*",
+        token::Slash => "/",
+        token::Percent => "%",
+        token::Caret => "^",
+        token::And => "&",
+        token::Or => "|",
+        token::Shl => "<<",
+        token::Shr => ">>",
     }
 }
 
@@ -221,10 +237,6 @@ pub fn stmt_to_string(stmt: &hir::Stmt) -> String {
     to_string(|s| s.print_stmt(stmt))
 }
 
-pub fn attr_to_string(attr: &hir::Attribute) -> String {
-    to_string(|s| s.print_attribute(attr))
-}
-
 pub fn item_to_string(i: &hir::Item) -> String {
     to_string(|s| s.print_item(i))
 }
@@ -253,21 +265,27 @@ pub fn path_to_string(p: &hir::Path) -> String {
     to_string(|s| s.print_path(p, false, 0))
 }
 
-pub fn ident_to_string(id: &ast::Ident) -> String {
-    to_string(|s| s.print_ident(*id))
+pub fn name_to_string(name: ast::Name) -> String {
+    to_string(|s| s.print_name(name))
 }
 
 pub fn fun_to_string(decl: &hir::FnDecl,
                      unsafety: hir::Unsafety,
                      constness: hir::Constness,
-                     name: ast::Ident,
+                     name: ast::Name,
                      opt_explicit_self: Option<&hir::ExplicitSelf_>,
                      generics: &hir::Generics)
                      -> String {
     to_string(|s| {
         try!(s.head(""));
-        try!(s.print_fn(decl, unsafety, constness, abi::Rust, Some(name),
-                        generics, opt_explicit_self, hir::Inherited));
+        try!(s.print_fn(decl,
+                        unsafety,
+                        constness,
+                        abi::Rust,
+                        Some(name),
+                        generics,
+                        opt_explicit_self,
+                        hir::Inherited));
         try!(s.end()); // Close the head box
         s.end() // Close the outer box
     })
@@ -283,18 +301,6 @@ pub fn block_to_string(blk: &hir::Block) -> String {
     })
 }
 
-pub fn meta_item_to_string(mi: &hir::MetaItem) -> String {
-    to_string(|s| s.print_meta_item(mi))
-}
-
-pub fn attribute_to_string(attr: &hir::Attribute) -> String {
-    to_string(|s| s.print_attribute(attr))
-}
-
-pub fn lit_to_string(l: &hir::Lit) -> String {
-    to_string(|s| s.print_literal(l))
-}
-
 pub fn explicit_self_to_string(explicit_self: &hir::ExplicitSelf_) -> String {
     to_string(|s| s.print_explicit_self(explicit_self, hir::MutImmutable).map(|_| {}))
 }
@@ -310,57 +316,36 @@ pub fn arg_to_string(arg: &hir::Arg) -> String {
 pub fn visibility_qualified(vis: hir::Visibility, s: &str) -> String {
     match vis {
         hir::Public => format!("pub {}", s),
-        hir::Inherited => s.to_string()
+        hir::Inherited => s.to_string(),
     }
 }
 
 fn needs_parentheses(expr: &hir::Expr) -> bool {
     match expr.node {
-        hir::ExprAssign(..) | hir::ExprBinary(..) |
+        hir::ExprAssign(..) |
+        hir::ExprBinary(..) |
         hir::ExprClosure(..) |
-        hir::ExprAssignOp(..) | hir::ExprCast(..) => true,
+        hir::ExprAssignOp(..) |
+        hir::ExprCast(..) => true,
         _ => false,
     }
 }
 
 impl<'a> State<'a> {
-    pub fn ibox(&mut self, u: usize) -> io::Result<()> {
-        self.boxes.push(pp::Breaks::Inconsistent);
-        pp::ibox(&mut self.s, u)
-    }
-
-    pub fn end(&mut self) -> io::Result<()> {
-        self.boxes.pop().unwrap();
-        pp::end(&mut self.s)
-    }
-
     pub fn cbox(&mut self, u: usize) -> io::Result<()> {
         self.boxes.push(pp::Breaks::Consistent);
         pp::cbox(&mut self.s, u)
     }
 
-    // "raw box"
-    pub fn rbox(&mut self, u: usize, b: pp::Breaks) -> io::Result<()> {
-        self.boxes.push(b);
-        pp::rbox(&mut self.s, u, b)
+    pub fn nbsp(&mut self) -> io::Result<()> {
+        word(&mut self.s, " ")
     }
 
-    pub fn nbsp(&mut self) -> io::Result<()> { word(&mut self.s, " ") }
-
     pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> {
         try!(word(&mut self.s, w));
         self.nbsp()
     }
 
-    pub fn word_space(&mut self, w: &str) -> io::Result<()> {
-        try!(word(&mut self.s, w));
-        space(&mut self.s)
-    }
-
-    pub fn popen(&mut self) -> io::Result<()> { word(&mut self.s, "(") }
-
-    pub fn pclose(&mut self) -> io::Result<()> { word(&mut self.s, ")") }
-
     pub fn head(&mut self, w: &str) -> io::Result<()> {
         // outer-box is consistent
         try!(self.cbox(indent_unit));
@@ -378,12 +363,14 @@ impl<'a> State<'a> {
         self.end() // close the head-box
     }
 
-    pub fn bclose_(&mut self, span: codemap::Span,
-                   indented: usize) -> io::Result<()> {
+    pub fn bclose_(&mut self, span: codemap::Span, indented: usize) -> io::Result<()> {
         self.bclose_maybe_open(span, indented, true)
     }
-    pub fn bclose_maybe_open (&mut self, span: codemap::Span,
-                              indented: usize, close_box: bool) -> io::Result<()> {
+    pub fn bclose_maybe_open(&mut self,
+                             span: codemap::Span,
+                             indented: usize,
+                             close_box: bool)
+                             -> io::Result<()> {
         try!(self.maybe_print_comment(span.hi));
         try!(self.break_offset_if_not_bol(1, -(indented as isize)));
         try!(word(&mut self.s, "}"));
@@ -396,44 +383,19 @@ impl<'a> State<'a> {
         self.bclose_(span, indent_unit)
     }
 
-    pub fn is_begin(&mut self) -> bool {
-        match self.s.last_token() {
-            pp::Token::Begin(_) => true,
-            _ => false,
-        }
-    }
-
-    pub fn is_end(&mut self) -> bool {
-        match self.s.last_token() {
-            pp::Token::End => true,
-            _ => false,
-        }
-    }
-
-    // is this the beginning of a line?
-    pub fn is_bol(&mut self) -> bool {
-        self.s.last_token().is_eof() || self.s.last_token().is_hardbreak_tok()
-    }
-
     pub fn in_cbox(&self) -> bool {
         match self.boxes.last() {
             Some(&last_box) => last_box == pp::Breaks::Consistent,
-            None => false
+            None => false,
         }
     }
-
-    pub fn hardbreak_if_not_bol(&mut self) -> io::Result<()> {
+    pub fn space_if_not_bol(&mut self) -> io::Result<()> {
         if !self.is_bol() {
-            try!(hardbreak(&mut self.s))
+            try!(space(&mut self.s));
         }
         Ok(())
     }
-    pub fn space_if_not_bol(&mut self) -> io::Result<()> {
-        if !self.is_bol() { try!(space(&mut self.s)); }
-        Ok(())
-    }
-    pub fn break_offset_if_not_bol(&mut self, n: usize,
-                                   off: isize) -> io::Result<()> {
+    pub fn break_offset_if_not_bol(&mut self, n: usize, off: isize) -> io::Result<()> {
         if !self.is_bol() {
             break_offset(&mut self.s, n, off)
         } else {
@@ -457,26 +419,15 @@ impl<'a> State<'a> {
         word(&mut self.s, "*/")
     }
 
-    pub fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], mut op: F) -> io::Result<()> where
-        F: FnMut(&mut State, &T) -> io::Result<()>,
-    {
-        try!(self.rbox(0, b));
-        let mut first = true;
-        for elt in elts {
-            if first { first = false; } else { try!(self.word_space(",")); }
-            try!(op(self, elt));
-        }
-        self.end()
-    }
-
 
     pub fn commasep_cmnt<T, F, G>(&mut self,
                                   b: Breaks,
                                   elts: &[T],
                                   mut op: F,
-                                  mut get_span: G) -> io::Result<()> where
-        F: FnMut(&mut State, &T) -> io::Result<()>,
-        G: FnMut(&T) -> codemap::Span,
+                                  mut get_span: G)
+                                  -> io::Result<()>
+        where F: FnMut(&mut State, &T) -> io::Result<()>,
+              G: FnMut(&T) -> codemap::Span
     {
         try!(self.rbox(0, b));
         let len = elts.len();
@@ -487,21 +438,18 @@ impl<'a> State<'a> {
             i += 1;
             if i < len {
                 try!(word(&mut self.s, ","));
-                try!(self.maybe_print_trailing_comment(get_span(elt),
-                                                    Some(get_span(&elts[i]).hi)));
+                try!(self.maybe_print_trailing_comment(get_span(elt), Some(get_span(&elts[i]).hi)));
                 try!(self.space_if_not_bol());
             }
         }
         self.end()
     }
 
-    pub fn commasep_exprs(&mut self, b: Breaks,
-                          exprs: &[P<hir::Expr>]) -> io::Result<()> {
+    pub fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<hir::Expr>]) -> io::Result<()> {
         self.commasep_cmnt(b, exprs, |s, e| s.print_expr(&**e), |e| e.span)
     }
 
-    pub fn print_mod(&mut self, _mod: &hir::Mod,
-                     attrs: &[hir::Attribute]) -> io::Result<()> {
+    pub fn print_mod(&mut self, _mod: &hir::Mod, attrs: &[ast::Attribute]) -> io::Result<()> {
         try!(self.print_inner_attributes(attrs));
         for item in &_mod.items {
             try!(self.print_item(&**item));
@@ -509,8 +457,10 @@ impl<'a> State<'a> {
         Ok(())
     }
 
-    pub fn print_foreign_mod(&mut self, nmod: &hir::ForeignMod,
-                             attrs: &[hir::Attribute]) -> io::Result<()> {
+    pub fn print_foreign_mod(&mut self,
+                             nmod: &hir::ForeignMod,
+                             attrs: &[ast::Attribute])
+                             -> io::Result<()> {
         try!(self.print_inner_attributes(attrs));
         for item in &nmod.items {
             try!(self.print_foreign_item(&**item));
@@ -518,8 +468,7 @@ impl<'a> State<'a> {
         Ok(())
     }
 
-    pub fn print_opt_lifetime(&mut self,
-                              lifetime: &Option<hir::Lifetime>) -> io::Result<()> {
+    pub fn print_opt_lifetime(&mut self, lifetime: &Option<hir::Lifetime>) -> io::Result<()> {
         if let Some(l) = *lifetime {
             try!(self.print_lifetime(&l));
             try!(self.nbsp());
@@ -551,8 +500,7 @@ impl<'a> State<'a> {
             }
             hir::TyTup(ref elts) => {
                 try!(self.popen());
-                try!(self.commasep(Inconsistent, &elts[..],
-                                   |s, ty| s.print_type(&**ty)));
+                try!(self.commasep(Inconsistent, &elts[..], |s, ty| s.print_type(&**ty)));
                 if elts.len() == 1 {
                     try!(word(&mut self.s, ","));
                 }
@@ -572,12 +520,7 @@ impl<'a> State<'a> {
                         predicates: Vec::new(),
                     },
                 };
-                try!(self.print_ty_fn(f.abi,
-                                      f.unsafety,
-                                      &*f.decl,
-                                      None,
-                                      &generics,
-                                      None));
+                try!(self.print_ty_fn(f.abi, f.unsafety, &*f.decl, None, &generics, None));
             }
             hir::TyPath(None, ref path) => {
                 try!(self.print_path(path, false, 0));
@@ -611,29 +554,31 @@ impl<'a> State<'a> {
         self.end()
     }
 
-    pub fn print_foreign_item(&mut self,
-                              item: &hir::ForeignItem) -> io::Result<()> {
+    pub fn print_foreign_item(&mut self, item: &hir::ForeignItem) -> io::Result<()> {
         try!(self.hardbreak_if_not_bol());
         try!(self.maybe_print_comment(item.span.lo));
         try!(self.print_outer_attributes(&item.attrs));
         match item.node {
             hir::ForeignItemFn(ref decl, ref generics) => {
                 try!(self.head(""));
-                try!(self.print_fn(decl, hir::Unsafety::Normal,
+                try!(self.print_fn(decl,
+                                   hir::Unsafety::Normal,
                                    hir::Constness::NotConst,
-                                   abi::Rust, Some(item.ident),
-                                   generics, None, item.vis));
+                                   abi::Rust,
+                                   Some(item.name),
+                                   generics,
+                                   None,
+                                   item.vis));
                 try!(self.end()); // end head-ibox
                 try!(word(&mut self.s, ";"));
                 self.end() // end the outer fn box
             }
             hir::ForeignItemStatic(ref t, m) => {
-                try!(self.head(&visibility_qualified(item.vis,
-                                                    "static")));
+                try!(self.head(&visibility_qualified(item.vis, "static")));
                 if m {
                     try!(self.word_space("mut"));
                 }
-                try!(self.print_ident(item.ident));
+                try!(self.print_name(item.name));
                 try!(self.word_space(":"));
                 try!(self.print_type(&**t));
                 try!(word(&mut self.s, ";"));
@@ -644,15 +589,14 @@ impl<'a> State<'a> {
     }
 
     fn print_associated_const(&mut self,
-                              ident: ast::Ident,
+                              name: ast::Name,
                               ty: &hir::Ty,
                               default: Option<&hir::Expr>,
                               vis: hir::Visibility)
-                              -> io::Result<()>
-    {
+                              -> io::Result<()> {
         try!(word(&mut self.s, &visibility_qualified(vis, "")));
         try!(self.word_space("const"));
-        try!(self.print_ident(ident));
+        try!(self.print_name(name));
         try!(self.word_space(":"));
         try!(self.print_type(ty));
         if let Some(expr) = default {
@@ -664,12 +608,12 @@ impl<'a> State<'a> {
     }
 
     fn print_associated_type(&mut self,
-                             ident: ast::Ident,
+                             name: ast::Name,
                              bounds: Option<&hir::TyParamBounds>,
                              ty: Option<&hir::Ty>)
                              -> io::Result<()> {
         try!(self.word_space("type"));
-        try!(self.print_ident(ident));
+        try!(self.print_name(name));
         if let Some(bounds) = bounds {
             try!(self.print_bounds(":", bounds));
         }
@@ -689,12 +633,11 @@ impl<'a> State<'a> {
         try!(self.ann.pre(self, NodeItem(item)));
         match item.node {
             hir::ItemExternCrate(ref optional_path) => {
-                try!(self.head(&visibility_qualified(item.vis,
-                                                     "extern crate")));
+                try!(self.head(&visibility_qualified(item.vis, "extern crate")));
                 if let Some(p) = *optional_path {
                     let val = p.as_str();
                     if val.contains("-") {
-                        try!(self.print_string(&val, hir::CookedStr));
+                        try!(self.print_string(&val, ast::CookedStr));
                     } else {
                         try!(self.print_name(p));
                     }
@@ -702,26 +645,24 @@ impl<'a> State<'a> {
                     try!(word(&mut self.s, "as"));
                     try!(space(&mut self.s));
                 }
-                try!(self.print_ident(item.ident));
+                try!(self.print_name(item.name));
                 try!(word(&mut self.s, ";"));
                 try!(self.end()); // end inner head-block
                 try!(self.end()); // end outer head-block
             }
             hir::ItemUse(ref vp) => {
-                try!(self.head(&visibility_qualified(item.vis,
-                                                     "use")));
+                try!(self.head(&visibility_qualified(item.vis, "use")));
                 try!(self.print_view_path(&**vp));
                 try!(word(&mut self.s, ";"));
                 try!(self.end()); // end inner head-block
                 try!(self.end()); // end outer head-block
             }
             hir::ItemStatic(ref ty, m, ref expr) => {
-                try!(self.head(&visibility_qualified(item.vis,
-                                                    "static")));
+                try!(self.head(&visibility_qualified(item.vis, "static")));
                 if m == hir::MutMutable {
                     try!(self.word_space("mut"));
                 }
-                try!(self.print_ident(item.ident));
+                try!(self.print_name(item.name));
                 try!(self.word_space(":"));
                 try!(self.print_type(&**ty));
                 try!(space(&mut self.s));
@@ -733,9 +674,8 @@ impl<'a> State<'a> {
                 try!(self.end()); // end the outer cbox
             }
             hir::ItemConst(ref ty, ref expr) => {
-                try!(self.head(&visibility_qualified(item.vis,
-                                                    "const")));
-                try!(self.print_ident(item.ident));
+                try!(self.head(&visibility_qualified(item.vis, "const")));
+                try!(self.print_name(item.name));
                 try!(self.word_space(":"));
                 try!(self.print_type(&**ty));
                 try!(space(&mut self.s));
@@ -748,23 +688,20 @@ impl<'a> State<'a> {
             }
             hir::ItemFn(ref decl, unsafety, constness, abi, ref typarams, ref body) => {
                 try!(self.head(""));
-                try!(self.print_fn(
-                    decl,
-                    unsafety,
-                    constness,
-                    abi,
-                    Some(item.ident),
-                    typarams,
-                    None,
-                    item.vis
-                ));
+                try!(self.print_fn(decl,
+                                   unsafety,
+                                   constness,
+                                   abi,
+                                   Some(item.name),
+                                   typarams,
+                                   None,
+                                   item.vis));
                 try!(word(&mut self.s, " "));
                 try!(self.print_block_with_attrs(&**body, &item.attrs));
             }
             hir::ItemMod(ref _mod) => {
-                try!(self.head(&visibility_qualified(item.vis,
-                                                    "mod")));
-                try!(self.print_ident(item.ident));
+                try!(self.head(&visibility_qualified(item.vis, "mod")));
+                try!(self.print_name(item.name));
                 try!(self.nbsp());
                 try!(self.bopen());
                 try!(self.print_mod(_mod, &item.attrs));
@@ -781,7 +718,7 @@ impl<'a> State<'a> {
                 try!(self.ibox(indent_unit));
                 try!(self.ibox(0));
                 try!(self.word_nbsp(&visibility_qualified(item.vis, "type")));
-                try!(self.print_ident(item.ident));
+                try!(self.print_name(item.name));
                 try!(self.print_generics(params));
                 try!(self.end()); // end the inner ibox
 
@@ -793,17 +730,11 @@ impl<'a> State<'a> {
                 try!(self.end()); // end the outer ibox
             }
             hir::ItemEnum(ref enum_definition, ref params) => {
-                try!(self.print_enum_def(
-                    enum_definition,
-                    params,
-                    item.ident,
-                    item.span,
-                    item.vis
-                ));
+                try!(self.print_enum_def(enum_definition, params, item.name, item.span, item.vis));
             }
             hir::ItemStruct(ref struct_def, ref generics) => {
-                try!(self.head(&visibility_qualified(item.vis,"struct")));
-                try!(self.print_struct(&**struct_def, generics, item.ident, item.span));
+                try!(self.head(&visibility_qualified(item.vis, "struct")));
+                try!(self.print_struct(struct_def, generics, item.name, item.span, true));
             }
 
             hir::ItemDefaultImpl(unsafety, ref trait_ref) => {
@@ -837,7 +768,7 @@ impl<'a> State<'a> {
                 match polarity {
                     hir::ImplPolarity::Negative => {
                         try!(word(&mut self.s, "!"));
-                    },
+                    }
                     _ => {}
                 }
 
@@ -866,7 +797,7 @@ impl<'a> State<'a> {
                 try!(self.print_visibility(item.vis));
                 try!(self.print_unsafety(unsafety));
                 try!(self.word_nbsp("trait"));
-                try!(self.print_ident(item.ident));
+                try!(self.print_name(item.name));
                 try!(self.print_generics(generics));
                 let mut real_bounds = Vec::with_capacity(bounds.len());
                 for b in bounds.iter() {
@@ -916,12 +847,15 @@ impl<'a> State<'a> {
         self.print_trait_ref(&t.trait_ref)
     }
 
-    pub fn print_enum_def(&mut self, enum_definition: &hir::EnumDef,
-                          generics: &hir::Generics, ident: ast::Ident,
+    pub fn print_enum_def(&mut self,
+                          enum_definition: &hir::EnumDef,
+                          generics: &hir::Generics,
+                          name: ast::Name,
                           span: codemap::Span,
-                          visibility: hir::Visibility) -> io::Result<()> {
+                          visibility: hir::Visibility)
+                          -> io::Result<()> {
         try!(self.head(&visibility_qualified(visibility, "enum")));
-        try!(self.print_ident(ident));
+        try!(self.print_name(name));
         try!(self.print_generics(generics));
         try!(self.print_where_clause(&generics.where_clause));
         try!(space(&mut self.s));
@@ -930,7 +864,8 @@ impl<'a> State<'a> {
 
     pub fn print_variants(&mut self,
                           variants: &[P<hir::Variant>],
-                          span: codemap::Span) -> io::Result<()> {
+                          span: codemap::Span)
+                          -> io::Result<()> {
         try!(self.bopen());
         for v in variants {
             try!(self.space_if_not_bol());
@@ -948,37 +883,40 @@ impl<'a> State<'a> {
     pub fn print_visibility(&mut self, vis: hir::Visibility) -> io::Result<()> {
         match vis {
             hir::Public => self.word_nbsp("pub"),
-            hir::Inherited => Ok(())
+            hir::Inherited => Ok(()),
         }
     }
 
     pub fn print_struct(&mut self,
-                        struct_def: &hir::StructDef,
+                        struct_def: &hir::VariantData,
                         generics: &hir::Generics,
-                        ident: ast::Ident,
-                        span: codemap::Span) -> io::Result<()> {
-        try!(self.print_ident(ident));
+                        name: ast::Name,
+                        span: codemap::Span,
+                        print_finalizer: bool)
+                        -> io::Result<()> {
+        try!(self.print_name(name));
         try!(self.print_generics(generics));
-        if ::util::struct_def_is_tuple_like(struct_def) {
-            if !struct_def.fields.is_empty() {
+        if !struct_def.is_struct() {
+            if struct_def.is_tuple() {
                 try!(self.popen());
-                try!(self.commasep(
-                    Inconsistent, &struct_def.fields,
-                    |s, field| {
-                        match field.node.kind {
-                            hir::NamedField(..) => panic!("unexpected named field"),
-                            hir::UnnamedField(vis) => {
-                                try!(s.print_visibility(vis));
-                                try!(s.maybe_print_comment(field.span.lo));
-                                s.print_type(&*field.node.ty)
-                            }
-                        }
-                    }
-                ));
+                try!(self.commasep(Inconsistent,
+                                   struct_def.fields(),
+                                   |s, field| {
+                                       match field.node.kind {
+                                           hir::NamedField(..) => panic!("unexpected named field"),
+                                           hir::UnnamedField(vis) => {
+                                               try!(s.print_visibility(vis));
+                                               try!(s.maybe_print_comment(field.span.lo));
+                                               s.print_type(&*field.node.ty)
+                                           }
+                                       }
+                                   }));
                 try!(self.pclose());
             }
             try!(self.print_where_clause(&generics.where_clause));
-            try!(word(&mut self.s, ";"));
+            if print_finalizer {
+                try!(word(&mut self.s, ";"));
+            }
             try!(self.end());
             self.end() // close the outer-box
         } else {
@@ -987,15 +925,15 @@ impl<'a> State<'a> {
             try!(self.bopen());
             try!(self.hardbreak_if_not_bol());
 
-            for field in &struct_def.fields {
+            for field in struct_def.fields() {
                 match field.node.kind {
                     hir::UnnamedField(..) => panic!("unexpected unnamed field"),
-                    hir::NamedField(ident, visibility) => {
+                    hir::NamedField(name, visibility) => {
                         try!(self.hardbreak_if_not_bol());
                         try!(self.maybe_print_comment(field.span.lo));
                         try!(self.print_outer_attributes(&field.node.attrs));
                         try!(self.print_visibility(visibility));
-                        try!(self.print_ident(ident));
+                        try!(self.print_name(name));
                         try!(self.word_nbsp(":"));
                         try!(self.print_type(&*field.node.ty));
                         try!(word(&mut self.s, ","));
@@ -1008,36 +946,21 @@ impl<'a> State<'a> {
     }
 
     pub fn print_variant(&mut self, v: &hir::Variant) -> io::Result<()> {
-        try!(self.print_visibility(v.node.vis));
-        match v.node.kind {
-            hir::TupleVariantKind(ref args) => {
-                try!(self.print_ident(v.node.name));
-                if !args.is_empty() {
-                    try!(self.popen());
-                    try!(self.commasep(Consistent,
-                                       &args[..],
-                                       |s, arg| s.print_type(&*arg.ty)));
-                    try!(self.pclose());
-                }
-            }
-            hir::StructVariantKind(ref struct_def) => {
-                try!(self.head(""));
-                let generics = ::util::empty_generics();
-                try!(self.print_struct(&**struct_def, &generics, v.node.name, v.span));
-            }
-        }
+        try!(self.head(""));
+        let generics = ::util::empty_generics();
+        try!(self.print_struct(&v.node.data, &generics, v.node.name, v.span, false));
         match v.node.disr_expr {
             Some(ref d) => {
                 try!(space(&mut self.s));
                 try!(self.word_space("="));
                 self.print_expr(&**d)
             }
-            _ => Ok(())
+            _ => Ok(()),
         }
     }
 
     pub fn print_method_sig(&mut self,
-                            ident: ast::Ident,
+                            name: ast::Name,
                             m: &hir::MethodSig,
                             vis: hir::Visibility)
                             -> io::Result<()> {
@@ -1045,21 +968,21 @@ impl<'a> State<'a> {
                       m.unsafety,
                       m.constness,
                       m.abi,
-                      Some(ident),
+                      Some(name),
                       &m.generics,
                       Some(&m.explicit_self.node),
                       vis)
     }
 
-    pub fn print_trait_item(&mut self, ti: &hir::TraitItem)
-                            -> io::Result<()> {
+    pub fn print_trait_item(&mut self, ti: &hir::TraitItem) -> io::Result<()> {
         try!(self.ann.pre(self, NodeSubItem(ti.id)));
         try!(self.hardbreak_if_not_bol());
         try!(self.maybe_print_comment(ti.span.lo));
         try!(self.print_outer_attributes(&ti.attrs));
         match ti.node {
             hir::ConstTraitItem(ref ty, ref default) => {
-                try!(self.print_associated_const(ti.ident, &ty,
+                try!(self.print_associated_const(ti.name,
+                                                 &ty,
                                                  default.as_ref().map(|expr| &**expr),
                                                  hir::Inherited));
             }
@@ -1067,7 +990,7 @@ impl<'a> State<'a> {
                 if body.is_some() {
                     try!(self.head(""));
                 }
-                try!(self.print_method_sig(ti.ident, sig, hir::Inherited));
+                try!(self.print_method_sig(ti.name, sig, hir::Inherited));
                 if let Some(ref body) = *body {
                     try!(self.nbsp());
                     try!(self.print_block_with_attrs(body, &ti.attrs));
@@ -1076,7 +999,8 @@ impl<'a> State<'a> {
                 }
             }
             hir::TypeTraitItem(ref bounds, ref default) => {
-                try!(self.print_associated_type(ti.ident, Some(bounds),
+                try!(self.print_associated_type(ti.name,
+                                                Some(bounds),
                                                 default.as_ref().map(|ty| &**ty)));
             }
         }
@@ -1090,73 +1014,21 @@ impl<'a> State<'a> {
         try!(self.print_outer_attributes(&ii.attrs));
         match ii.node {
             hir::ConstImplItem(ref ty, ref expr) => {
-                try!(self.print_associated_const(ii.ident, &ty, Some(&expr), ii.vis));
+                try!(self.print_associated_const(ii.name, &ty, Some(&expr), ii.vis));
             }
             hir::MethodImplItem(ref sig, ref body) => {
                 try!(self.head(""));
-                try!(self.print_method_sig(ii.ident, sig, ii.vis));
+                try!(self.print_method_sig(ii.name, sig, ii.vis));
                 try!(self.nbsp());
                 try!(self.print_block_with_attrs(body, &ii.attrs));
             }
             hir::TypeImplItem(ref ty) => {
-                try!(self.print_associated_type(ii.ident, None, Some(ty)));
+                try!(self.print_associated_type(ii.name, None, Some(ty)));
             }
         }
         self.ann.post(self, NodeSubItem(ii.id))
     }
 
-    pub fn print_outer_attributes(&mut self,
-                                  attrs: &[hir::Attribute]) -> io::Result<()> {
-        let mut count = 0;
-        for attr in attrs {
-            match attr.node.style {
-                hir::AttrOuter => {
-                    try!(self.print_attribute(attr));
-                    count += 1;
-                }
-                _ => {/* fallthrough */ }
-            }
-        }
-        if count > 0 {
-            try!(self.hardbreak_if_not_bol());
-        }
-        Ok(())
-    }
-
-    pub fn print_inner_attributes(&mut self,
-                                  attrs: &[hir::Attribute]) -> io::Result<()> {
-        let mut count = 0;
-        for attr in attrs {
-            match attr.node.style {
-                hir::AttrInner => {
-                    try!(self.print_attribute(attr));
-                    count += 1;
-                }
-                _ => {/* fallthrough */ }
-            }
-        }
-        if count > 0 {
-            try!(self.hardbreak_if_not_bol());
-        }
-        Ok(())
-    }
-
-    pub fn print_attribute(&mut self, attr: &hir::Attribute) -> io::Result<()> {
-        try!(self.hardbreak_if_not_bol());
-        try!(self.maybe_print_comment(attr.span.lo));
-        if attr.node.is_sugared_doc {
-            word(&mut self.s, &attr.value_str().unwrap())
-        } else {
-            match attr.node.style {
-                hir::AttrInner => try!(word(&mut self.s, "#![")),
-                hir::AttrOuter => try!(word(&mut self.s, "#[")),
-            }
-            try!(self.print_meta_item(&*attr.meta()));
-            word(&mut self.s, "]")
-        }
-    }
-
-
     pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> {
         try!(self.maybe_print_comment(st.span.lo));
         match st.node {
@@ -1187,25 +1059,33 @@ impl<'a> State<'a> {
         self.print_block_unclosed_indent(blk, indent_unit)
     }
 
-    pub fn print_block_unclosed_indent(&mut self, blk: &hir::Block,
-                                       indented: usize) -> io::Result<()> {
+    pub fn print_block_unclosed_indent(&mut self,
+                                       blk: &hir::Block,
+                                       indented: usize)
+                                       -> io::Result<()> {
         self.print_block_maybe_unclosed(blk, indented, &[], false)
     }
 
     pub fn print_block_with_attrs(&mut self,
                                   blk: &hir::Block,
-                                  attrs: &[hir::Attribute]) -> io::Result<()> {
+                                  attrs: &[ast::Attribute])
+                                  -> io::Result<()> {
         self.print_block_maybe_unclosed(blk, indent_unit, attrs, true)
     }
 
     pub fn print_block_maybe_unclosed(&mut self,
                                       blk: &hir::Block,
                                       indented: usize,
-                                      attrs: &[hir::Attribute],
-                                      close_box: bool) -> io::Result<()> {
+                                      attrs: &[ast::Attribute],
+                                      close_box: bool)
+                                      -> io::Result<()> {
         match blk.rules {
-            hir::UnsafeBlock(..) | hir::PushUnsafeBlock(..) => try!(self.word_space("unsafe")),
-            hir::DefaultBlock    | hir::PopUnsafeBlock(..) => ()
+            hir::UnsafeBlock(..) => try!(self.word_space("unsafe")),
+            hir::PushUnsafeBlock(..) => try!(self.word_space("push_unsafe")),
+            hir::PopUnsafeBlock(..) => try!(self.word_space("pop_unsafe")),
+            hir::PushUnstableBlock => try!(self.word_space("push_unstable")),
+            hir::PopUnstableBlock => try!(self.word_space("pop_unstable")),
+            hir::DefaultBlock => (),
         }
         try!(self.maybe_print_comment(blk.span.lo));
         try!(self.ann.pre(self, NodeBlock(blk)));
@@ -1222,7 +1102,7 @@ impl<'a> State<'a> {
                 try!(self.print_expr(&**expr));
                 try!(self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi)));
             }
-            _ => ()
+            _ => (),
         }
         try!(self.bclose_maybe_open(blk.span, indented, close_box));
         self.ann.post(self, NodeBlock(blk))
@@ -1255,12 +1135,15 @@ impl<'a> State<'a> {
                     }
                 }
             }
-            _ => Ok(())
+            _ => Ok(()),
         }
     }
 
-    pub fn print_if(&mut self, test: &hir::Expr, blk: &hir::Block,
-                    elseopt: Option<&hir::Expr>) -> io::Result<()> {
+    pub fn print_if(&mut self,
+                    test: &hir::Expr,
+                    blk: &hir::Block,
+                    elseopt: Option<&hir::Expr>)
+                    -> io::Result<()> {
         try!(self.head("if"));
         try!(self.print_expr(test));
         try!(space(&mut self.s));
@@ -1268,8 +1151,12 @@ impl<'a> State<'a> {
         self.print_else(elseopt)
     }
 
-    pub fn print_if_let(&mut self, pat: &hir::Pat, expr: &hir::Expr, blk: &hir::Block,
-                        elseopt: Option<&hir::Expr>) -> io::Result<()> {
+    pub fn print_if_let(&mut self,
+                        pat: &hir::Pat,
+                        expr: &hir::Expr,
+                        blk: &hir::Block,
+                        elseopt: Option<&hir::Expr>)
+                        -> io::Result<()> {
         try!(self.head("if let"));
         try!(self.print_pat(pat));
         try!(space(&mut self.s));
@@ -1299,16 +1186,6 @@ impl<'a> State<'a> {
         Ok(())
     }
 
-    fn print_expr_box(&mut self,
-                      place: &Option<P<hir::Expr>>,
-                      expr: &hir::Expr) -> io::Result<()> {
-        try!(word(&mut self.s, "box"));
-        try!(word(&mut self.s, "("));
-        try!(place.as_ref().map_or(Ok(()), |e|self.print_expr(&**e)));
-        try!(self.word_space(")"));
-        self.print_expr(expr)
-    }
-
     fn print_expr_vec(&mut self, exprs: &[P<hir::Expr>]) -> io::Result<()> {
         try!(self.ibox(indent_unit));
         try!(word(&mut self.s, "["));
@@ -1317,9 +1194,7 @@ impl<'a> State<'a> {
         self.end()
     }
 
-    fn print_expr_repeat(&mut self,
-                         element: &hir::Expr,
-                         count: &hir::Expr) -> io::Result<()> {
+    fn print_expr_repeat(&mut self, element: &hir::Expr, count: &hir::Expr) -> io::Result<()> {
         try!(self.ibox(indent_unit));
         try!(word(&mut self.s, "["));
         try!(self.print_expr(element));
@@ -1332,36 +1207,36 @@ impl<'a> State<'a> {
     fn print_expr_struct(&mut self,
                          path: &hir::Path,
                          fields: &[hir::Field],
-                         wth: &Option<P<hir::Expr>>) -> io::Result<()> {
+                         wth: &Option<P<hir::Expr>>)
+                         -> io::Result<()> {
         try!(self.print_path(path, true, 0));
-        if !(fields.is_empty() && wth.is_none()) {
-            try!(word(&mut self.s, "{"));
-            try!(self.commasep_cmnt(
-                Consistent,
-                &fields[..],
-                |s, field| {
-                    try!(s.ibox(indent_unit));
-                    try!(s.print_ident(field.ident.node));
-                    try!(s.word_space(":"));
-                    try!(s.print_expr(&*field.expr));
-                    s.end()
-                },
-                |f| f.span));
-            match *wth {
-                Some(ref expr) => {
-                    try!(self.ibox(indent_unit));
-                    if !fields.is_empty() {
-                        try!(word(&mut self.s, ","));
-                        try!(space(&mut self.s));
-                    }
-                    try!(word(&mut self.s, ".."));
-                    try!(self.print_expr(&**expr));
-                    try!(self.end());
+        try!(word(&mut self.s, "{"));
+        try!(self.commasep_cmnt(Consistent,
+                                &fields[..],
+                                |s, field| {
+                                    try!(s.ibox(indent_unit));
+                                    try!(s.print_name(field.name.node));
+                                    try!(s.word_space(":"));
+                                    try!(s.print_expr(&*field.expr));
+                                    s.end()
+                                },
+                                |f| f.span));
+        match *wth {
+            Some(ref expr) => {
+                try!(self.ibox(indent_unit));
+                if !fields.is_empty() {
+                    try!(word(&mut self.s, ","));
+                    try!(space(&mut self.s));
                 }
-                _ => try!(word(&mut self.s, ",")),
+                try!(word(&mut self.s, ".."));
+                try!(self.print_expr(&**expr));
+                try!(self.end());
             }
-            try!(word(&mut self.s, "}"));
+            _ => if !fields.is_empty() {
+                try!(word(&mut self.s, ","))
+            },
         }
+        try!(word(&mut self.s, "}"));
         Ok(())
     }
 
@@ -1374,25 +1249,23 @@ impl<'a> State<'a> {
         self.pclose()
     }
 
-    fn print_expr_call(&mut self,
-                       func: &hir::Expr,
-                       args: &[P<hir::Expr>]) -> io::Result<()> {
+    fn print_expr_call(&mut self, func: &hir::Expr, args: &[P<hir::Expr>]) -> io::Result<()> {
         try!(self.print_expr_maybe_paren(func));
         self.print_call_post(args)
     }
 
     fn print_expr_method_call(&mut self,
-                              ident: hir::SpannedIdent,
+                              name: Spanned<ast::Name>,
                               tys: &[P<hir::Ty>],
-                              args: &[P<hir::Expr>]) -> io::Result<()> {
+                              args: &[P<hir::Expr>])
+                              -> io::Result<()> {
         let base_args = &args[1..];
         try!(self.print_expr(&*args[0]));
         try!(word(&mut self.s, "."));
-        try!(self.print_ident(ident.node));
+        try!(self.print_name(name.node));
         if !tys.is_empty() {
             try!(word(&mut self.s, "::<"));
-            try!(self.commasep(Inconsistent, tys,
-                               |s, ty| s.print_type(&**ty)));
+            try!(self.commasep(Inconsistent, tys, |s, ty| s.print_type(&**ty)));
             try!(word(&mut self.s, ">"));
         }
         self.print_call_post(base_args)
@@ -1401,23 +1274,23 @@ impl<'a> State<'a> {
     fn print_expr_binary(&mut self,
                          op: hir::BinOp,
                          lhs: &hir::Expr,
-                         rhs: &hir::Expr) -> io::Result<()> {
+                         rhs: &hir::Expr)
+                         -> io::Result<()> {
         try!(self.print_expr(lhs));
         try!(space(&mut self.s));
         try!(self.word_space(::util::binop_to_string(op.node)));
         self.print_expr(rhs)
     }
 
-    fn print_expr_unary(&mut self,
-                        op: hir::UnOp,
-                        expr: &hir::Expr) -> io::Result<()> {
+    fn print_expr_unary(&mut self, op: hir::UnOp, expr: &hir::Expr) -> io::Result<()> {
         try!(word(&mut self.s, ::util::unop_to_string(op)));
         self.print_expr_maybe_paren(expr)
     }
 
     fn print_expr_addr_of(&mut self,
                           mutability: hir::Mutability,
-                          expr: &hir::Expr) -> io::Result<()> {
+                          expr: &hir::Expr)
+                          -> io::Result<()> {
         try!(word(&mut self.s, "&"));
         try!(self.print_mutability(mutability));
         self.print_expr_maybe_paren(expr)
@@ -1428,8 +1301,9 @@ impl<'a> State<'a> {
         try!(self.ibox(indent_unit));
         try!(self.ann.pre(self, NodeExpr(expr)));
         match expr.node {
-            hir::ExprBox(ref place, ref expr) => {
-                try!(self.print_expr_box(place, &**expr));
+            hir::ExprBox(ref expr) => {
+                try!(self.word_space("box"));
+                try!(self.print_expr(expr));
             }
             hir::ExprVec(ref exprs) => {
                 try!(self.print_expr_vec(&exprs[..]));
@@ -1446,8 +1320,8 @@ impl<'a> State<'a> {
             hir::ExprCall(ref func, ref args) => {
                 try!(self.print_expr_call(&**func, &args[..]));
             }
-            hir::ExprMethodCall(ident, ref tys, ref args) => {
-                try!(self.print_expr_method_call(ident, &tys[..], &args[..]));
+            hir::ExprMethodCall(name, ref tys, ref args) => {
+                try!(self.print_expr_method_call(name, &tys[..], &args[..]));
             }
             hir::ExprBinary(op, ref lhs, ref rhs) => {
                 try!(self.print_expr_binary(op, &**lhs, &**rhs));
@@ -1472,7 +1346,7 @@ impl<'a> State<'a> {
             }
             hir::ExprWhile(ref test, ref blk, opt_ident) => {
                 if let Some(ident) = opt_ident {
-                    try!(self.print_ident(ident));
+                    try!(self.print_name(ident.name));
                     try!(self.word_space(":"));
                 }
                 try!(self.head("while"));
@@ -1482,7 +1356,7 @@ impl<'a> State<'a> {
             }
             hir::ExprLoop(ref blk, opt_ident) => {
                 if let Some(ident) = opt_ident {
-                    try!(self.print_ident(ident));
+                    try!(self.print_name(ident.name));
                     try!(self.word_space(":"));
                 }
                 try!(self.head("loop"));
@@ -1509,7 +1383,7 @@ impl<'a> State<'a> {
 
                 let default_return = match decl.output {
                     hir::DefaultReturn(..) => true,
-                    _ => false
+                    _ => false,
                 };
 
                 if !default_return || !body.stmts.is_empty() || body.expr.is_none() {
@@ -1552,10 +1426,10 @@ impl<'a> State<'a> {
                 try!(self.word_space("="));
                 try!(self.print_expr(&**rhs));
             }
-            hir::ExprField(ref expr, id) => {
+            hir::ExprField(ref expr, name) => {
                 try!(self.print_expr(&**expr));
                 try!(word(&mut self.s, "."));
-                try!(self.print_ident(id.node));
+                try!(self.print_name(name.node));
             }
             hir::ExprTupField(ref expr, id) => {
                 try!(self.print_expr(&**expr));
@@ -1587,7 +1461,7 @@ impl<'a> State<'a> {
                 try!(word(&mut self.s, "break"));
                 try!(space(&mut self.s));
                 if let Some(ident) = opt_ident {
-                    try!(self.print_ident(ident.node));
+                    try!(self.print_name(ident.node.name));
                     try!(space(&mut self.s));
                 }
             }
@@ -1595,7 +1469,7 @@ impl<'a> State<'a> {
                 try!(word(&mut self.s, "continue"));
                 try!(space(&mut self.s));
                 if let Some(ident) = opt_ident {
-                    try!(self.print_ident(ident.node));
+                    try!(self.print_name(ident.node.name));
                     try!(space(&mut self.s))
                 }
             }
@@ -1606,7 +1480,7 @@ impl<'a> State<'a> {
                         try!(word(&mut self.s, " "));
                         try!(self.print_expr(&**expr));
                     }
-                    _ => ()
+                    _ => (),
                 }
             }
             hir::ExprInlineAsm(ref a) => {
@@ -1615,39 +1489,42 @@ impl<'a> State<'a> {
                 try!(self.print_string(&a.asm, a.asm_str_style));
                 try!(self.word_space(":"));
 
-                try!(self.commasep(Inconsistent, &a.outputs,
+                try!(self.commasep(Inconsistent,
+                                   &a.outputs,
                                    |s, &(ref co, ref o, is_rw)| {
-                    match co.slice_shift_char() {
-                        Some(('=', operand)) if is_rw => {
-                            try!(s.print_string(&format!("+{}", operand),
-                                                hir::CookedStr))
-                        }
-                        _ => try!(s.print_string(&co, hir::CookedStr))
-                    }
-                    try!(s.popen());
-                    try!(s.print_expr(&**o));
-                    try!(s.pclose());
-                    Ok(())
-                }));
+                                       match co.slice_shift_char() {
+                                           Some(('=', operand)) if is_rw => {
+                                               try!(s.print_string(&format!("+{}", operand),
+                                                                   ast::CookedStr))
+                                           }
+                                           _ => try!(s.print_string(&co, ast::CookedStr)),
+                                       }
+                                       try!(s.popen());
+                                       try!(s.print_expr(&**o));
+                                       try!(s.pclose());
+                                       Ok(())
+                                   }));
                 try!(space(&mut self.s));
                 try!(self.word_space(":"));
 
-                try!(self.commasep(Inconsistent, &a.inputs,
+                try!(self.commasep(Inconsistent,
+                                   &a.inputs,
                                    |s, &(ref co, ref o)| {
-                    try!(s.print_string(&co, hir::CookedStr));
-                    try!(s.popen());
-                    try!(s.print_expr(&**o));
-                    try!(s.pclose());
-                    Ok(())
-                }));
+                                       try!(s.print_string(&co, ast::CookedStr));
+                                       try!(s.popen());
+                                       try!(s.print_expr(&**o));
+                                       try!(s.pclose());
+                                       Ok(())
+                                   }));
                 try!(space(&mut self.s));
                 try!(self.word_space(":"));
 
-                try!(self.commasep(Inconsistent, &a.clobbers,
+                try!(self.commasep(Inconsistent,
+                                   &a.clobbers,
                                    |s, co| {
-                    try!(s.print_string(&co, hir::CookedStr));
-                    Ok(())
-                }));
+                                       try!(s.print_string(&co, ast::CookedStr));
+                                       Ok(())
+                                   }));
 
                 let mut options = vec!();
                 if a.volatile {
@@ -1656,27 +1533,23 @@ impl<'a> State<'a> {
                 if a.alignstack {
                     options.push("alignstack");
                 }
-                if a.dialect == hir::AsmDialect::AsmIntel {
+                if a.dialect == ast::AsmDialect::Intel {
                     options.push("intel");
                 }
 
                 if !options.is_empty() {
                     try!(space(&mut self.s));
                     try!(self.word_space(":"));
-                    try!(self.commasep(Inconsistent, &*options,
+                    try!(self.commasep(Inconsistent,
+                                       &*options,
                                        |s, &co| {
-                        try!(s.print_string(co, hir::CookedStr));
-                        Ok(())
-                    }));
+                                           try!(s.print_string(co, ast::CookedStr));
+                                           Ok(())
+                                       }));
                 }
 
                 try!(self.pclose());
             }
-            hir::ExprParen(ref e) => {
-                try!(self.popen());
-                try!(self.print_expr(&**e));
-                try!(self.pclose());
-            }
         }
         try!(self.ann.post(self, NodeExpr(expr)));
         self.end()
@@ -1709,15 +1582,10 @@ impl<'a> State<'a> {
                 }
                 self.end()
             }
-            hir::DeclItem(ref item) => self.print_item(&**item)
+            hir::DeclItem(ref item) => self.print_item(&**item),
         }
     }
 
-    pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> {
-        try!(word(&mut self.s, &ident.name.as_str()));
-        self.ann.post(self, NodeIdent(&ident))
-    }
-
     pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
         word(&mut self.s, &i.to_string())
     }
@@ -1727,8 +1595,7 @@ impl<'a> State<'a> {
         self.ann.post(self, NodeName(&name))
     }
 
-    pub fn print_for_decl(&mut self, loc: &hir::Local,
-                          coll: &hir::Expr) -> io::Result<()> {
+    pub fn print_for_decl(&mut self, loc: &hir::Local, coll: &hir::Expr) -> io::Result<()> {
         try!(self.print_local_decl(loc));
         try!(space(&mut self.s));
         try!(self.word_space("in"));
@@ -1739,8 +1606,7 @@ impl<'a> State<'a> {
                   path: &hir::Path,
                   colons_before_params: bool,
                   depth: usize)
-                  -> io::Result<()>
-    {
+                  -> io::Result<()> {
         try!(self.maybe_print_comment(path.span.lo));
 
         let mut first = !path.global;
@@ -1751,7 +1617,7 @@ impl<'a> State<'a> {
                 try!(word(&mut self.s, "::"))
             }
 
-            try!(self.print_ident(segment.identifier));
+            try!(self.print_name(segment.identifier.name));
 
             try!(self.print_path_parameters(&segment.parameters, colons_before_params));
         }
@@ -1763,8 +1629,7 @@ impl<'a> State<'a> {
                    path: &hir::Path,
                    qself: &hir::QSelf,
                    colons_before_params: bool)
-                   -> io::Result<()>
-    {
+                   -> io::Result<()> {
         try!(word(&mut self.s, "<"));
         try!(self.print_type(&qself.ty));
         if qself.position > 0 {
@@ -1776,15 +1641,14 @@ impl<'a> State<'a> {
         try!(word(&mut self.s, ">"));
         try!(word(&mut self.s, "::"));
         let item_segment = path.segments.last().unwrap();
-        try!(self.print_ident(item_segment.identifier));
+        try!(self.print_name(item_segment.identifier.name));
         self.print_path_parameters(&item_segment.parameters, colons_before_params)
     }
 
     fn print_path_parameters(&mut self,
                              parameters: &hir::PathParameters,
                              colons_before_params: bool)
-                             -> io::Result<()>
-    {
+                             -> io::Result<()> {
         if parameters.is_empty() {
             return Ok(());
         }
@@ -1810,18 +1674,15 @@ impl<'a> State<'a> {
                     if comma {
                         try!(self.word_space(","))
                     }
-                    try!(self.commasep(
-                        Inconsistent,
-                        &data.types,
-                        |s, ty| s.print_type(&**ty)));
-                        comma = true;
+                    try!(self.commasep(Inconsistent, &data.types, |s, ty| s.print_type(&**ty)));
+                    comma = true;
                 }
 
                 for binding in data.bindings.iter() {
                     if comma {
                         try!(self.word_space(","))
                     }
-                    try!(self.print_ident(binding.ident));
+                    try!(self.print_name(binding.name));
                     try!(space(&mut self.s));
                     try!(self.word_space("="));
                     try!(self.print_type(&*binding.ty));
@@ -1833,14 +1694,13 @@ impl<'a> State<'a> {
 
             hir::ParenthesizedParameters(ref data) => {
                 try!(word(&mut self.s, "("));
-                try!(self.commasep(
-                    Inconsistent,
-                    &data.inputs,
-                    |s, ty| s.print_type(&**ty)));
+                try!(self.commasep(Inconsistent,
+                                   &data.inputs,
+                                   |s, ty| s.print_type(&**ty)));
                 try!(word(&mut self.s, ")"));
 
                 match data.output {
-                    None => { }
+                    None => {}
                     Some(ref ty) => {
                         try!(self.space_if_not_bol());
                         try!(self.word_space("->"));
@@ -1872,13 +1732,13 @@ impl<'a> State<'a> {
                         try!(self.word_nbsp("mut"));
                     }
                 }
-                try!(self.print_ident(path1.node));
+                try!(self.print_name(path1.node.name));
                 match *sub {
                     Some(ref p) => {
                         try!(word(&mut self.s, "@"));
                         try!(self.print_pat(&**p));
                     }
-                    None => ()
+                    None => (),
                 }
             }
             hir::PatEnum(ref path, ref args_) => {
@@ -1888,8 +1748,7 @@ impl<'a> State<'a> {
                     Some(ref args) => {
                         if !args.is_empty() {
                             try!(self.popen());
-                            try!(self.commasep(Inconsistent, &args[..],
-                                              |s, p| s.print_pat(&**p)));
+                            try!(self.commasep(Inconsistent, &args[..], |s, p| s.print_pat(&**p)));
                             try!(self.pclose());
                         }
                     }
@@ -1902,20 +1761,22 @@ impl<'a> State<'a> {
                 try!(self.print_path(path, true, 0));
                 try!(self.nbsp());
                 try!(self.word_space("{"));
-                try!(self.commasep_cmnt(
-                    Consistent, &fields[..],
-                    |s, f| {
-                        try!(s.cbox(indent_unit));
-                        if !f.node.is_shorthand {
-                            try!(s.print_ident(f.node.ident));
-                            try!(s.word_nbsp(":"));
-                        }
-                        try!(s.print_pat(&*f.node.pat));
-                        s.end()
-                    },
-                    |f| f.node.pat.span));
+                try!(self.commasep_cmnt(Consistent,
+                                        &fields[..],
+                                        |s, f| {
+                                            try!(s.cbox(indent_unit));
+                                            if !f.node.is_shorthand {
+                                                try!(s.print_name(f.node.name));
+                                                try!(s.word_nbsp(":"));
+                                            }
+                                            try!(s.print_pat(&*f.node.pat));
+                                            s.end()
+                                        },
+                                        |f| f.node.pat.span));
                 if etc {
-                    if !fields.is_empty() { try!(self.word_space(",")); }
+                    if !fields.is_empty() {
+                        try!(self.word_space(","));
+                    }
                     try!(word(&mut self.s, ".."));
                 }
                 try!(space(&mut self.s));
@@ -1923,9 +1784,7 @@ impl<'a> State<'a> {
             }
             hir::PatTup(ref elts) => {
                 try!(self.popen());
-                try!(self.commasep(Inconsistent,
-                                   &elts[..],
-                                   |s, p| s.print_pat(&**p)));
+                try!(self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&**p)));
                 if elts.len() == 1 {
                     try!(word(&mut self.s, ","));
                 }
@@ -1951,11 +1810,11 @@ impl<'a> State<'a> {
             }
             hir::PatVec(ref before, ref slice, ref after) => {
                 try!(word(&mut self.s, "["));
-                try!(self.commasep(Inconsistent,
-                                   &before[..],
-                                   |s, p| s.print_pat(&**p)));
+                try!(self.commasep(Inconsistent, &before[..], |s, p| s.print_pat(&**p)));
                 if let Some(ref p) = *slice {
-                    if !before.is_empty() { try!(self.word_space(",")); }
+                    if !before.is_empty() {
+                        try!(self.word_space(","));
+                    }
                     try!(self.print_pat(&**p));
                     match **p {
                         hir::Pat { node: hir::PatWild(hir::PatWildMulti), .. } => {
@@ -1963,11 +1822,11 @@ impl<'a> State<'a> {
                         }
                         _ => try!(word(&mut self.s, "..")),
                     }
-                    if !after.is_empty() { try!(self.word_space(",")); }
+                    if !after.is_empty() {
+                        try!(self.word_space(","));
+                    }
                 }
-                try!(self.commasep(Inconsistent,
-                                   &after[..],
-                                   |s, p| s.print_pat(&**p)));
+                try!(self.commasep(Inconsistent, &after[..], |s, p| s.print_pat(&**p)));
                 try!(word(&mut self.s, "]"));
             }
         }
@@ -2023,10 +1882,13 @@ impl<'a> State<'a> {
     // Returns whether it printed anything
     fn print_explicit_self(&mut self,
                            explicit_self: &hir::ExplicitSelf_,
-                           mutbl: hir::Mutability) -> io::Result<bool> {
+                           mutbl: hir::Mutability)
+                           -> io::Result<bool> {
         try!(self.print_mutability(mutbl));
         match *explicit_self {
-            hir::SelfStatic => { return Ok(false); }
+            hir::SelfStatic => {
+                return Ok(false);
+            }
             hir::SelfValue(_) => {
                 try!(word(&mut self.s, "self"));
             }
@@ -2050,24 +1912,26 @@ impl<'a> State<'a> {
                     unsafety: hir::Unsafety,
                     constness: hir::Constness,
                     abi: abi::Abi,
-                    name: Option<ast::Ident>,
+                    name: Option<ast::Name>,
                     generics: &hir::Generics,
                     opt_explicit_self: Option<&hir::ExplicitSelf_>,
-                    vis: hir::Visibility) -> io::Result<()> {
+                    vis: hir::Visibility)
+                    -> io::Result<()> {
         try!(self.print_fn_header_info(unsafety, constness, abi, vis));
 
         if let Some(name) = name {
             try!(self.nbsp());
-            try!(self.print_ident(name));
+            try!(self.print_name(name));
         }
         try!(self.print_generics(generics));
         try!(self.print_fn_args_and_ret(decl, opt_explicit_self));
         self.print_where_clause(&generics.where_clause)
     }
 
-    pub fn print_fn_args(&mut self, decl: &hir::FnDecl,
+    pub fn print_fn_args(&mut self,
+                         decl: &hir::FnDecl,
                          opt_explicit_self: Option<&hir::ExplicitSelf_>)
-        -> io::Result<()> {
+                         -> io::Result<()> {
         // It is unfortunate to duplicate the commasep logic, but we want the
         // self type and the args all in the same box.
         try!(self.rbox(0, Inconsistent));
@@ -2077,8 +1941,8 @@ impl<'a> State<'a> {
                 &hir::SelfStatic => hir::MutImmutable,
                 _ => match decl.inputs[0].pat.node {
                     hir::PatIdent(hir::BindByValue(m), _, _) => m,
-                    _ => hir::MutImmutable
-                }
+                    _ => hir::MutImmutable,
+                },
             };
             first = !try!(self.print_explicit_self(explicit_self, m));
         }
@@ -2091,16 +1955,21 @@ impl<'a> State<'a> {
         };
 
         for arg in args {
-            if first { first = false; } else { try!(self.word_space(",")); }
+            if first {
+                first = false;
+            } else {
+                try!(self.word_space(","));
+            }
             try!(self.print_arg(arg));
         }
 
         self.end()
     }
 
-    pub fn print_fn_args_and_ret(&mut self, decl: &hir::FnDecl,
+    pub fn print_fn_args_and_ret(&mut self,
+                                 decl: &hir::FnDecl,
                                  opt_explicit_self: Option<&hir::ExplicitSelf_>)
-        -> io::Result<()> {
+                                 -> io::Result<()> {
         try!(self.popen());
         try!(self.print_fn_args(decl, opt_explicit_self));
         if decl.variadic {
@@ -2111,10 +1980,7 @@ impl<'a> State<'a> {
         self.print_fn_output(decl)
     }
 
-    pub fn print_fn_block_args(
-            &mut self,
-            decl: &hir::FnDecl)
-            -> io::Result<()> {
+    pub fn print_fn_block_args(&mut self, decl: &hir::FnDecl) -> io::Result<()> {
         try!(word(&mut self.s, "|"));
         try!(self.print_fn_args(decl, None));
         try!(word(&mut self.s, "|"));
@@ -2138,18 +2004,14 @@ impl<'a> State<'a> {
         }
     }
 
-    pub fn print_capture_clause(&mut self, capture_clause: hir::CaptureClause)
-                                -> io::Result<()> {
+    pub fn print_capture_clause(&mut self, capture_clause: hir::CaptureClause) -> io::Result<()> {
         match capture_clause {
             hir::CaptureByValue => self.word_space("move"),
             hir::CaptureByRef => Ok(()),
         }
     }
 
-    pub fn print_bounds(&mut self,
-                        prefix: &str,
-                        bounds: &[hir::TyParamBound])
-                        -> io::Result<()> {
+    pub fn print_bounds(&mut self, prefix: &str, bounds: &[hir::TyParamBound]) -> io::Result<()> {
         if !bounds.is_empty() {
             try!(word(&mut self.s, prefix));
             let mut first = true;
@@ -2180,17 +2042,11 @@ impl<'a> State<'a> {
         }
     }
 
-    pub fn print_lifetime(&mut self,
-                          lifetime: &hir::Lifetime)
-                          -> io::Result<()>
-    {
+    pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> {
         self.print_name(lifetime.name)
     }
 
-    pub fn print_lifetime_def(&mut self,
-                              lifetime: &hir::LifetimeDef)
-                              -> io::Result<()>
-    {
+    pub fn print_lifetime_def(&mut self, lifetime: &hir::LifetimeDef) -> io::Result<()> {
         try!(self.print_lifetime(&lifetime.lifetime));
         let mut sep = ":";
         for v in &lifetime.bounds {
@@ -2201,10 +2057,7 @@ impl<'a> State<'a> {
         Ok(())
     }
 
-    pub fn print_generics(&mut self,
-                          generics: &hir::Generics)
-                          -> io::Result<()>
-    {
+    pub fn print_generics(&mut self, generics: &hir::Generics) -> io::Result<()> {
         let total = generics.lifetimes.len() + generics.ty_params.len();
         if total == 0 {
             return Ok(());
@@ -2217,23 +2070,25 @@ impl<'a> State<'a> {
             ints.push(i);
         }
 
-        try!(self.commasep(Inconsistent, &ints[..], |s, &idx| {
-            if idx < generics.lifetimes.len() {
-                let lifetime = &generics.lifetimes[idx];
-                s.print_lifetime_def(lifetime)
-            } else {
-                let idx = idx - generics.lifetimes.len();
-                let param = &generics.ty_params[idx];
-                s.print_ty_param(param)
-            }
-        }));
+        try!(self.commasep(Inconsistent,
+                           &ints[..],
+                           |s, &idx| {
+                               if idx < generics.lifetimes.len() {
+                                   let lifetime = &generics.lifetimes[idx];
+                                   s.print_lifetime_def(lifetime)
+                               } else {
+                                   let idx = idx - generics.lifetimes.len();
+                                   let param = &generics.ty_params[idx];
+                                   s.print_ty_param(param)
+                               }
+                           }));
 
         try!(word(&mut self.s, ">"));
         Ok(())
     }
 
     pub fn print_ty_param(&mut self, param: &hir::TyParam) -> io::Result<()> {
-        try!(self.print_ident(param.ident));
+        try!(self.print_name(param.name));
         try!(self.print_bounds(":", &param.bounds));
         match param.default {
             Some(ref default) => {
@@ -2241,12 +2096,11 @@ impl<'a> State<'a> {
                 try!(self.word_space("="));
                 self.print_type(&**default)
             }
-            _ => Ok(())
+            _ => Ok(()),
         }
     }
 
-    pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause)
-                              -> io::Result<()> {
+    pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) -> io::Result<()> {
         if where_clause.predicates.is_empty() {
             return Ok(())
         }
@@ -2294,40 +2148,15 @@ impl<'a> State<'a> {
         Ok(())
     }
 
-    pub fn print_meta_item(&mut self, item: &hir::MetaItem) -> io::Result<()> {
-        try!(self.ibox(indent_unit));
-        match item.node {
-            hir::MetaWord(ref name) => {
-                try!(word(&mut self.s, &name));
-            }
-            hir::MetaNameValue(ref name, ref value) => {
-                try!(self.word_space(&name[..]));
-                try!(self.word_space("="));
-                try!(self.print_literal(value));
-            }
-            hir::MetaList(ref name, ref items) => {
-                try!(word(&mut self.s, &name));
-                try!(self.popen());
-                try!(self.commasep(Consistent,
-                                   &items[..],
-                                   |s, i| s.print_meta_item(&**i)));
-                try!(self.pclose());
-            }
-        }
-        self.end()
-    }
-
     pub fn print_view_path(&mut self, vp: &hir::ViewPath) -> io::Result<()> {
         match vp.node {
-            hir::ViewPathSimple(ident, ref path) => {
+            hir::ViewPathSimple(name, ref path) => {
                 try!(self.print_path(path, false, 0));
 
-                // FIXME(#6993) can't compare identifiers directly here
-                if path.segments.last().unwrap().identifier.name !=
-                        ident.name {
+                if path.segments.last().unwrap().identifier.name != name {
                     try!(space(&mut self.s));
                     try!(self.word_space("as"));
-                    try!(self.print_ident(ident));
+                    try!(self.print_name(name));
                 }
 
                 Ok(())
@@ -2338,30 +2167,31 @@ impl<'a> State<'a> {
                 word(&mut self.s, "::*")
             }
 
-            hir::ViewPathList(ref path, ref idents) => {
+            hir::ViewPathList(ref path, ref segments) => {
                 if path.segments.is_empty() {
                     try!(word(&mut self.s, "{"));
                 } else {
                     try!(self.print_path(path, false, 0));
                     try!(word(&mut self.s, "::{"));
                 }
-                try!(self.commasep(Inconsistent, &idents[..], |s, w| {
-                    match w.node {
-                        hir::PathListIdent { name, .. } => {
-                            s.print_ident(name)
-                        },
-                        hir::PathListMod { .. } => {
-                            word(&mut s.s, "self")
-                        }
-                    }
-                }));
+                try!(self.commasep(Inconsistent,
+                                   &segments[..],
+                                   |s, w| {
+                                       match w.node {
+                                           hir::PathListIdent { name, .. } => {
+                                               s.print_name(name)
+                                           }
+                                           hir::PathListMod { .. } => {
+                                               word(&mut s.s, "self")
+                                           }
+                                       }
+                                   }));
                 word(&mut self.s, "}")
             }
         }
     }
 
-    pub fn print_mutability(&mut self,
-                            mutbl: hir::Mutability) -> io::Result<()> {
+    pub fn print_mutability(&mut self, mutbl: hir::Mutability) -> io::Result<()> {
         match mutbl {
             hir::MutMutable => self.word_nbsp("mut"),
             hir::MutImmutable => Ok(()),
@@ -2405,17 +2235,15 @@ impl<'a> State<'a> {
         try!(self.ibox(indent_unit));
         try!(self.word_space("->"));
         match decl.output {
-            hir::NoReturn(_) =>
-                try!(self.word_nbsp("!")),
+            hir::NoReturn(_) => try!(self.word_nbsp("!")),
             hir::DefaultReturn(..) => unreachable!(),
-            hir::Return(ref ty) =>
-                try!(self.print_type(&**ty))
+            hir::Return(ref ty) => try!(self.print_type(&**ty)),
         }
         try!(self.end());
 
         match decl.output {
             hir::Return(ref output) => self.maybe_print_comment(output.span.lo),
-            _ => Ok(())
+            _ => Ok(()),
         }
     }
 
@@ -2423,7 +2251,7 @@ impl<'a> State<'a> {
                        abi: abi::Abi,
                        unsafety: hir::Unsafety,
                        decl: &hir::FnDecl,
-                       name: Option<ast::Ident>,
+                       name: Option<ast::Name>,
                        generics: &hir::Generics,
                        opt_explicit_self: Option<&hir::ExplicitSelf_>)
                        -> io::Result<()> {
@@ -2451,27 +2279,33 @@ impl<'a> State<'a> {
         self.end()
     }
 
-    pub fn maybe_print_trailing_comment(&mut self, span: codemap::Span,
+    pub fn maybe_print_trailing_comment(&mut self,
+                                        span: codemap::Span,
                                         next_pos: Option<BytePos>)
-        -> io::Result<()> {
+                                        -> io::Result<()> {
         let cm = match self.cm {
             Some(cm) => cm,
-            _ => return Ok(())
+            _ => return Ok(()),
         };
         match self.next_comment() {
             Some(ref cmnt) => {
-                if (*cmnt).style != comments::Trailing { return Ok(()) }
+                if (*cmnt).style != comments::Trailing {
+                    return Ok(())
+                }
                 let span_line = cm.lookup_char_pos(span.hi);
                 let comment_line = cm.lookup_char_pos((*cmnt).pos);
                 let mut next = (*cmnt).pos + BytePos(1);
-                match next_pos { None => (), Some(p) => next = p }
+                match next_pos {
+                    None => (),
+                    Some(p) => next = p,
+                }
                 if span.hi < (*cmnt).pos && (*cmnt).pos < next &&
-                    span_line.line == comment_line.line {
-                        try!(self.print_comment(cmnt));
-                        self.cur_cmnt_and_lit.cur_cmnt += 1;
-                    }
+                   span_line.line == comment_line.line {
+                    try!(self.print_comment(cmnt));
+                    self.cur_cmnt_and_lit.cur_cmnt += 1;
+                }
             }
-            _ => ()
+            _ => (),
         }
         Ok(())
     }
@@ -2488,208 +2322,32 @@ impl<'a> State<'a> {
                     try!(self.print_comment(cmnt));
                     self.cur_cmnt_and_lit.cur_cmnt += 1;
                 }
-                _ => break
-            }
-        }
-        Ok(())
-    }
-
-    pub fn print_literal(&mut self, lit: &hir::Lit) -> io::Result<()> {
-        try!(self.maybe_print_comment(lit.span.lo));
-        match self.next_lit(lit.span.lo) {
-            Some(ref ltrl) => {
-                return word(&mut self.s, &(*ltrl).lit);
-            }
-            _ => ()
-        }
-        match lit.node {
-            hir::LitStr(ref st, style) => self.print_string(&st, style),
-            hir::LitByte(byte) => {
-                let mut res = String::from("b'");
-                res.extend(ascii::escape_default(byte).map(|c| c as char));
-                res.push('\'');
-                word(&mut self.s, &res[..])
-            }
-            hir::LitChar(ch) => {
-                let mut res = String::from("'");
-                res.extend(ch.escape_default());
-                res.push('\'');
-                word(&mut self.s, &res[..])
-            }
-            hir::LitInt(i, t) => {
-                match t {
-                    hir::SignedIntLit(st, hir::Plus) => {
-                        word(&mut self.s,
-                             &::util::int_ty_to_string(st, Some(i as i64)))
-                    }
-                    hir::SignedIntLit(st, hir::Minus) => {
-                        let istr = ::util::int_ty_to_string(st, Some(-(i as i64)));
-                        word(&mut self.s,
-                             &format!("-{}", istr))
-                    }
-                    hir::UnsignedIntLit(ut) => {
-                        word(&mut self.s, &::util::uint_ty_to_string(ut, Some(i)))
-                    }
-                    hir::UnsuffixedIntLit(hir::Plus) => {
-                        word(&mut self.s, &format!("{}", i))
-                    }
-                    hir::UnsuffixedIntLit(hir::Minus) => {
-                        word(&mut self.s, &format!("-{}", i))
-                    }
-                }
-            }
-            hir::LitFloat(ref f, t) => {
-                word(&mut self.s,
-                     &format!(
-                         "{}{}",
-                         &f,
-                         &::util::float_ty_to_string(t)))
-            }
-            hir::LitFloatUnsuffixed(ref f) => word(&mut self.s, &f[..]),
-            hir::LitBool(val) => {
-                if val { word(&mut self.s, "true") } else { word(&mut self.s, "false") }
-            }
-            hir::LitByteStr(ref v) => {
-                let mut escaped: String = String::new();
-                for &ch in v.iter() {
-                    escaped.extend(ascii::escape_default(ch)
-                                         .map(|c| c as char));
-                }
-                word(&mut self.s, &format!("b\"{}\"", escaped))
-            }
-        }
-    }
-
-    pub fn next_lit(&mut self, pos: BytePos) -> Option<comments::Literal> {
-        match self.literals {
-            Some(ref lits) => {
-                while self.cur_cmnt_and_lit.cur_lit < lits.len() {
-                    let ltrl = (*lits)[self.cur_cmnt_and_lit.cur_lit].clone();
-                    if ltrl.pos > pos { return None; }
-                    self.cur_cmnt_and_lit.cur_lit += 1;
-                    if ltrl.pos == pos { return Some(ltrl); }
-                }
-                None
-            }
-            _ => None
-        }
-    }
-
-    pub fn maybe_print_comment(&mut self, pos: BytePos) -> io::Result<()> {
-        loop {
-            match self.next_comment() {
-                Some(ref cmnt) => {
-                    if (*cmnt).pos < pos {
-                        try!(self.print_comment(cmnt));
-                        self.cur_cmnt_and_lit.cur_cmnt += 1;
-                    } else { break; }
-                }
-                _ => break
+                _ => break,
             }
         }
         Ok(())
     }
 
-    pub fn print_comment(&mut self,
-                         cmnt: &comments::Comment) -> io::Result<()> {
-        match cmnt.style {
-            comments::Mixed => {
-                assert_eq!(cmnt.lines.len(), 1);
-                try!(zerobreak(&mut self.s));
-                try!(word(&mut self.s, &cmnt.lines[0]));
-                zerobreak(&mut self.s)
-            }
-            comments::Isolated => {
-                try!(self.hardbreak_if_not_bol());
-                for line in &cmnt.lines {
-                    // Don't print empty lines because they will end up as trailing
-                    // whitespace
-                    if !line.is_empty() {
-                        try!(word(&mut self.s, &line[..]));
-                    }
-                    try!(hardbreak(&mut self.s));
-                }
-                Ok(())
-            }
-            comments::Trailing => {
-                try!(word(&mut self.s, " "));
-                if cmnt.lines.len() == 1 {
-                    try!(word(&mut self.s, &cmnt.lines[0]));
-                    hardbreak(&mut self.s)
-                } else {
-                    try!(self.ibox(0));
-                    for line in &cmnt.lines {
-                        if !line.is_empty() {
-                            try!(word(&mut self.s, &line[..]));
-                        }
-                        try!(hardbreak(&mut self.s));
-                    }
-                    self.end()
-                }
-            }
-            comments::BlankLine => {
-                // We need to do at least one, possibly two hardbreaks.
-                let is_semi = match self.s.last_token() {
-                    pp::Token::String(s, _) => ";" == s,
-                    _ => false
-                };
-                if is_semi || self.is_begin() || self.is_end() {
-                    try!(hardbreak(&mut self.s));
-                }
-                hardbreak(&mut self.s)
-            }
-        }
-    }
-
-    pub fn print_string(&mut self, st: &str,
-                        style: hir::StrStyle) -> io::Result<()> {
-        let st = match style {
-            hir::CookedStr => {
-                (format!("\"{}\"", st.escape_default()))
-            }
-            hir::RawStr(n) => {
-                (format!("r{delim}\"{string}\"{delim}",
-                         delim=repeat("#", n),
-                         string=st))
-            }
-        };
-        word(&mut self.s, &st[..])
-    }
-
-    pub fn next_comment(&mut self) -> Option<comments::Comment> {
-        match self.comments {
-            Some(ref cmnts) => {
-                if self.cur_cmnt_and_lit.cur_cmnt < cmnts.len() {
-                    Some(cmnts[self.cur_cmnt_and_lit.cur_cmnt].clone())
-                } else {
-                    None
-                }
-            }
-            _ => None
-        }
-    }
-
     pub fn print_opt_abi_and_extern_if_nondefault(&mut self,
                                                   opt_abi: Option<abi::Abi>)
-        -> io::Result<()> {
+                                                  -> io::Result<()> {
         match opt_abi {
             Some(abi::Rust) => Ok(()),
             Some(abi) => {
                 try!(self.word_nbsp("extern"));
                 self.word_nbsp(&abi.to_string())
             }
-            None => Ok(())
+            None => Ok(()),
         }
     }
 
-    pub fn print_extern_opt_abi(&mut self,
-                                opt_abi: Option<abi::Abi>) -> io::Result<()> {
+    pub fn print_extern_opt_abi(&mut self, opt_abi: Option<abi::Abi>) -> io::Result<()> {
         match opt_abi {
             Some(abi) => {
                 try!(self.word_nbsp("extern"));
                 self.word_nbsp(&abi.to_string())
             }
-            None => Ok(())
+            None => Ok(()),
         }
     }
 
@@ -2697,13 +2355,14 @@ impl<'a> State<'a> {
                                 unsafety: hir::Unsafety,
                                 constness: hir::Constness,
                                 abi: abi::Abi,
-                                vis: hir::Visibility) -> io::Result<()> {
+                                vis: hir::Visibility)
+                                -> io::Result<()> {
         try!(word(&mut self.s, &visibility_qualified(vis, "")));
         try!(self.print_unsafety(unsafety));
 
         match constness {
             hir::Constness::NotConst => {}
-            hir::Constness::Const => try!(self.word_nbsp("const"))
+            hir::Constness::Const => try!(self.word_nbsp("const")),
         }
 
         if abi != abi::Rust {
@@ -2722,8 +2381,6 @@ impl<'a> State<'a> {
     }
 }
 
-fn repeat(s: &str, n: usize) -> String { iter::repeat(s).take(n).collect() }
-
 // Dup'ed from parse::classify, but adapted for the HIR.
 /// Does this expression require a semicolon to be treated
 /// as a statement? The negation of this: 'can this expression
@@ -2734,12 +2391,12 @@ fn repeat(s: &str, n: usize) -> String { iter::repeat(s).take(n).collect() }
 /// isn't parsed as (if true {...} else {...} | x) | 5
 fn expr_requires_semi_to_be_stmt(e: &hir::Expr) -> bool {
     match e.node {
-        hir::ExprIf(..)
-        | hir::ExprMatch(..)
-        | hir::ExprBlock(_)
-        | hir::ExprWhile(..)
-        hir::ExprLoop(..) => false,
-        _ => true
+        hir::ExprIf(..) |
+        hir::ExprMatch(..) |
+        hir::ExprBlock(_) |
+        hir::ExprWhile(..) |
+        hir::ExprLoop(..) => false,
+        _ => true,
     }
 }
 
@@ -2751,10 +2408,14 @@ fn stmt_ends_with_semi(stmt: &hir::Stmt_) -> bool {
         hir::StmtDecl(ref d, _) => {
             match d.node {
                 hir::DeclLocal(_) => true,
-                hir::DeclItem(_) => false
+                hir::DeclItem(_) => false,
             }
         }
-        hir::StmtExpr(ref e, _) => { expr_requires_semi_to_be_stmt(&**e) }
-        hir::StmtSemi(..) => { false }
+        hir::StmtExpr(ref e, _) => {
+            expr_requires_semi_to_be_stmt(&**e)
+        }
+        hir::StmtSemi(..) => {
+            false
+        }
     }
 }
index 247ea2ea23b8cb63fec155efb728549e515d53e0..5d8973ead47db27a1ddea1bc4a8128d9c7834b01 100644 (file)
@@ -12,14 +12,18 @@ use hir;
 use hir::*;
 use visit::{self, Visitor, FnKind};
 use syntax::ast_util;
-use syntax::ast::{Ident, NodeId, DUMMY_NODE_ID};
+use syntax::ast::{Ident, Name, NodeId, DUMMY_NODE_ID};
 use syntax::codemap::Span;
 use syntax::ptr::P;
 use syntax::owned_slice::OwnedSlice;
 
-pub fn walk_pat<F>(pat: &Pat, mut it: F) -> bool where F: FnMut(&Pat) -> bool {
+pub fn walk_pat<F>(pat: &Pat, mut it: F) -> bool
+    where F: FnMut(&Pat) -> bool
+{
     // FIXME(#19596) this is a workaround, but there should be a better way
-    fn walk_pat_<G>(pat: &Pat, it: &mut G) -> bool where G: FnMut(&Pat) -> bool {
+    fn walk_pat_<G>(pat: &Pat, it: &mut G) -> bool
+        where G: FnMut(&Pat) -> bool
+    {
         if !(*it)(pat) {
             return false;
         }
@@ -40,8 +44,12 @@ pub fn walk_pat<F>(pat: &Pat, mut it: F) -> bool where F: FnMut(&Pat) -> bool {
                 slice.iter().all(|p| walk_pat_(&**p, it)) &&
                 after.iter().all(|p| walk_pat_(&**p, it))
             }
-            PatWild(_) | PatLit(_) | PatRange(_, _) | PatIdent(_, _, _) |
-            PatEnum(_, _) | PatQPath(_, _) => {
+            PatWild(_) |
+            PatLit(_) |
+            PatRange(_, _) |
+            PatIdent(_, _, _) |
+            PatEnum(_, _) |
+            PatQPath(_, _) => {
                 true
             }
         }
@@ -69,47 +77,49 @@ pub fn binop_to_string(op: BinOp_) -> &'static str {
         BiLe => "<=",
         BiNe => "!=",
         BiGe => ">=",
-        BiGt => ">"
+        BiGt => ">",
     }
 }
 
-/// Returns true if the given struct def is tuple-like; i.e. that its fields
-/// are unnamed.
-pub fn struct_def_is_tuple_like(struct_def: &hir::StructDef) -> bool {
-    struct_def.ctor_id.is_some()
-}
-
 pub fn stmt_id(s: &Stmt) -> NodeId {
     match s.node {
-      StmtDecl(_, id) => id,
-      StmtExpr(_, id) => id,
-      StmtSemi(_, id) => id,
+        StmtDecl(_, id) => id,
+        StmtExpr(_, id) => id,
+        StmtSemi(_, id) => id,
     }
 }
 
 pub fn lazy_binop(b: BinOp_) -> bool {
     match b {
-      BiAnd => true,
-      BiOr => true,
-      _ => false
+        BiAnd => true,
+        BiOr => true,
+        _ => false,
     }
 }
 
 pub fn is_shift_binop(b: BinOp_) -> bool {
     match b {
-      BiShl => true,
-      BiShr => true,
-      _ => false
+        BiShl => true,
+        BiShr => true,
+        _ => false,
     }
 }
 
 pub fn is_comparison_binop(b: BinOp_) -> bool {
     match b {
-        BiEq | BiLt | BiLe | BiNe | BiGt | BiGe =>
-            true,
-        BiAnd | BiOr | BiAdd | BiSub | BiMul | BiDiv | BiRem |
-        BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr =>
-            false,
+        BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => true,
+        BiAnd |
+        BiOr |
+        BiAdd |
+        BiSub |
+        BiMul |
+        BiDiv |
+        BiRem |
+        BiBitXor |
+        BiBitAnd |
+        BiBitOr |
+        BiShl |
+        BiShr => false,
     }
 }
 
@@ -128,14 +138,13 @@ pub fn is_by_value_unop(u: UnOp) -> bool {
 
 pub fn unop_to_string(op: UnOp) -> &'static str {
     match op {
-      UnUniq => "box() ",
-      UnDeref => "*",
-      UnNot => "!",
-      UnNeg => "-",
+        UnDeref => "*",
+        UnNot => "!",
+        UnNeg => "-",
     }
 }
 
-pub struct IdVisitor<'a, O:'a> {
+pub struct IdVisitor<'a, O: 'a> {
     pub operation: &'a mut O,
     pub pass_through_items: bool,
     pub visited_outermost: bool,
@@ -153,10 +162,7 @@ impl<'a, O: ast_util::IdVisitingOperation> IdVisitor<'a, O> {
 }
 
 impl<'a, 'v, O: ast_util::IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
-    fn visit_mod(&mut self,
-                 module: &Mod,
-                 _: Span,
-                 node_id: NodeId) {
+    fn visit_mod(&mut self, module: &Mod, _: Span, node_id: NodeId) {
         self.operation.visit_id(node_id);
         visit::walk_mod(self, module)
     }
@@ -188,11 +194,6 @@ impl<'a, 'v, O: ast_util::IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O>
                     }
                 }
             }
-            ItemEnum(ref enum_definition, _) => {
-                for variant in &enum_definition.variants {
-                    self.operation.visit_id(variant.node.id)
-                }
-            }
             _ => {}
         }
 
@@ -266,11 +267,7 @@ impl<'a, 'v, O: ast_util::IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O>
             self.operation.visit_id(argument.id)
         }
 
-        visit::walk_fn(self,
-                       function_kind,
-                       function_declaration,
-                       block,
-                       span);
+        visit::walk_fn(self, function_kind, function_declaration, block, span);
 
         if !self.pass_through_items {
             if let FnKind::Method(..) = function_kind {
@@ -284,13 +281,13 @@ impl<'a, 'v, O: ast_util::IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O>
         visit::walk_struct_field(self, struct_field)
     }
 
-    fn visit_struct_def(&mut self,
-                        struct_def: &StructDef,
-                        _: Ident,
+    fn visit_variant_data(&mut self,
+                        struct_def: &VariantData,
+                        _: Name,
                         _: &hir::Generics,
-                        id: NodeId) {
-        self.operation.visit_id(id);
-        struct_def.ctor_id.map(|ctor_id| self.operation.visit_id(ctor_id));
+                        _: NodeId,
+                        _: Span) {
+        self.operation.visit_id(struct_def.id());
         visit::walk_struct_def(self, struct_def);
     }
 
@@ -304,12 +301,12 @@ impl<'a, 'v, O: ast_util::IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O>
         visit::walk_impl_item(self, ii);
     }
 
-    fn visit_lifetime_ref(&mut self, lifetime: &Lifetime) {
+    fn visit_lifetime(&mut self, lifetime: &Lifetime) {
         self.operation.visit_id(lifetime.id);
     }
 
     fn visit_lifetime_def(&mut self, def: &LifetimeDef) {
-        self.visit_lifetime_ref(&def.lifetime);
+        self.visit_lifetime(&def.lifetime);
     }
 
     fn visit_trait_ref(&mut self, trait_ref: &TraitRef) {
@@ -324,11 +321,8 @@ pub fn compute_id_range_for_fn_body(fk: FnKind,
                                     body: &Block,
                                     sp: Span,
                                     id: NodeId)
-                                    -> ast_util::IdRange
-{
-    let mut visitor = ast_util::IdRangeComputingVisitor {
-        result: ast_util::IdRange::max()
-    };
+                                    -> ast_util::IdRange {
+    let mut visitor = ast_util::IdRangeComputingVisitor { result: ast_util::IdRange::max() };
     let mut id_visitor = IdVisitor {
         operation: &mut visitor,
         pass_through_items: false,
@@ -338,64 +332,13 @@ pub fn compute_id_range_for_fn_body(fk: FnKind,
     id_visitor.operation.result
 }
 
-/// Returns true if this literal is a string and false otherwise.
-pub fn lit_is_str(lit: &Lit) -> bool {
-    match lit.node {
-        LitStr(..) => true,
-        _ => false,
-    }
-}
-
 pub fn is_path(e: P<Expr>) -> bool {
-    match e.node { ExprPath(..) => true, _ => false }
-}
-
-/// Get a string representation of a signed int type, with its value.
-/// We want to avoid "45int" and "-3int" in favor of "45" and "-3"
-pub fn int_ty_to_string(t: IntTy, val: Option<i64>) -> String {
-    let s = match t {
-        TyIs => "isize",
-        TyI8 => "i8",
-        TyI16 => "i16",
-        TyI32 => "i32",
-        TyI64 => "i64"
-    };
-
-    match val {
-        // cast to a u64 so we can correctly print INT64_MIN. All integral types
-        // are parsed as u64, so we wouldn't want to print an extra negative
-        // sign.
-        Some(n) => format!("{}{}", n as u64, s),
-        None => s.to_string()
-    }
-}
-
-
-/// Get a string representation of an unsigned int type, with its value.
-/// We want to avoid "42u" in favor of "42us". "42uint" is right out.
-pub fn uint_ty_to_string(t: UintTy, val: Option<u64>) -> String {
-    let s = match t {
-        TyUs => "usize",
-        TyU8 => "u8",
-        TyU16 => "u16",
-        TyU32 => "u32",
-        TyU64 => "u64"
-    };
-
-    match val {
-        Some(n) => format!("{}{}", n, s),
-        None => s.to_string()
-    }
-}
-
-pub fn float_ty_to_string(t: FloatTy) -> String {
-    match t {
-        TyF32 => "f32".to_string(),
-        TyF64 => "f64".to_string(),
+    match e.node {
+        ExprPath(..) => true,
+        _ => false,
     }
 }
 
-
 pub fn empty_generics() -> Generics {
     Generics {
         lifetimes: Vec::new(),
@@ -403,25 +346,23 @@ pub fn empty_generics() -> Generics {
         where_clause: WhereClause {
             id: DUMMY_NODE_ID,
             predicates: Vec::new(),
-        }
+        },
     }
 }
 
 // convert a span and an identifier to the corresponding
 // 1-segment path
-pub fn ident_to_path(s: Span, identifier: Ident) -> Path {
+pub fn ident_to_path(s: Span, ident: Ident) -> Path {
     hir::Path {
         span: s,
         global: false,
-        segments: vec!(
-            hir::PathSegment {
-                identifier: identifier,
-                parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
-                    lifetimes: Vec::new(),
-                    types: OwnedSlice::empty(),
-                    bindings: OwnedSlice::empty(),
-                })
-            }
-        ),
+        segments: vec!(hir::PathSegment {
+            identifier: ident,
+            parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
+                lifetimes: Vec::new(),
+                types: OwnedSlice::empty(),
+                bindings: OwnedSlice::empty(),
+            }),
+        }),
     }
 }
index f20e5345f20668145159109abba3f6b29b93f9e3..547651bef8670d21197400e1d71070aefe458d8e 100644 (file)
 //! those that are created by the expansion of a macro.
 
 use syntax::abi::Abi;
-use syntax::ast::{Ident, NodeId, CRATE_NODE_ID, Name};
-use hir::*;
-use hir;
+use syntax::ast::{Ident, NodeId, CRATE_NODE_ID, Name, Attribute};
 use syntax::codemap::Span;
-use syntax::ptr::P;
-use syntax::owned_slice::OwnedSlice;
+use hir::*;
 
 #[derive(Copy, Clone, PartialEq, Eq)]
 pub enum FnKind<'a> {
     /// fn foo() or extern "Abi" fn foo()
-    ItemFn(Ident, &'a Generics, Unsafety, Constness, Abi, Visibility),
+    ItemFn(Name, &'a Generics, Unsafety, Constness, Abi, Visibility),
 
     /// fn foo(&self)
-    Method(Ident, &'a MethodSig, Option<Visibility>),
+    Method(Name, &'a MethodSig, Option<Visibility>),
 
-    /// |x, y| ...
-    /// proc(x, y) ...
+    /// |x, y| {}
     Closure,
 }
 
@@ -58,59 +54,80 @@ pub trait Visitor<'v> : Sized {
         // Nothing to do.
     }
     fn visit_ident(&mut self, span: Span, ident: Ident) {
-        self.visit_name(span, ident.name);
-    }
-    fn visit_mod(&mut self, m: &'v Mod, _s: Span, _n: NodeId) { walk_mod(self, m) }
-    fn visit_foreign_item(&mut self, i: &'v ForeignItem) { walk_foreign_item(self, i) }
-    fn visit_item(&mut self, i: &'v Item) { walk_item(self, i) }
-    fn visit_local(&mut self, l: &'v Local) { walk_local(self, l) }
-    fn visit_block(&mut self, b: &'v Block) { walk_block(self, b) }
-    fn visit_stmt(&mut self, s: &'v Stmt) { walk_stmt(self, s) }
-    fn visit_arm(&mut self, a: &'v Arm) { walk_arm(self, a) }
-    fn visit_pat(&mut self, p: &'v Pat) { walk_pat(self, p) }
-    fn visit_decl(&mut self, d: &'v Decl) { walk_decl(self, d) }
-    fn visit_expr(&mut self, ex: &'v Expr) { walk_expr(self, ex) }
-    fn visit_expr_post(&mut self, _ex: &'v Expr) { }
-    fn visit_ty(&mut self, t: &'v Ty) { walk_ty(self, t) }
-    fn visit_generics(&mut self, g: &'v Generics) { walk_generics(self, g) }
+        walk_ident(self, span, ident);
+    }
+    fn visit_mod(&mut self, m: &'v Mod, _s: Span, _n: NodeId) {
+        walk_mod(self, m)
+    }
+    fn visit_foreign_item(&mut self, i: &'v ForeignItem) {
+        walk_foreign_item(self, i)
+    }
+    fn visit_item(&mut self, i: &'v Item) {
+        walk_item(self, i)
+    }
+    fn visit_local(&mut self, l: &'v Local) {
+        walk_local(self, l)
+    }
+    fn visit_block(&mut self, b: &'v Block) {
+        walk_block(self, b)
+    }
+    fn visit_stmt(&mut self, s: &'v Stmt) {
+        walk_stmt(self, s)
+    }
+    fn visit_arm(&mut self, a: &'v Arm) {
+        walk_arm(self, a)
+    }
+    fn visit_pat(&mut self, p: &'v Pat) {
+        walk_pat(self, p)
+    }
+    fn visit_decl(&mut self, d: &'v Decl) {
+        walk_decl(self, d)
+    }
+    fn visit_expr(&mut self, ex: &'v Expr) {
+        walk_expr(self, ex)
+    }
+    fn visit_expr_post(&mut self, _ex: &'v Expr) {
+    }
+    fn visit_ty(&mut self, t: &'v Ty) {
+        walk_ty(self, t)
+    }
+    fn visit_generics(&mut self, g: &'v Generics) {
+        walk_generics(self, g)
+    }
     fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Block, s: Span, _: NodeId) {
         walk_fn(self, fk, fd, b, s)
     }
-    fn visit_trait_item(&mut self, ti: &'v TraitItem) { walk_trait_item(self, ti) }
-    fn visit_impl_item(&mut self, ii: &'v ImplItem) { walk_impl_item(self, ii) }
-    fn visit_trait_ref(&mut self, t: &'v TraitRef) { walk_trait_ref(self, t) }
+    fn visit_trait_item(&mut self, ti: &'v TraitItem) {
+        walk_trait_item(self, ti)
+    }
+    fn visit_impl_item(&mut self, ii: &'v ImplItem) {
+        walk_impl_item(self, ii)
+    }
+    fn visit_trait_ref(&mut self, t: &'v TraitRef) {
+        walk_trait_ref(self, t)
+    }
     fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) {
         walk_ty_param_bound(self, bounds)
     }
     fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) {
         walk_poly_trait_ref(self, t, m)
     }
-    fn visit_struct_def(&mut self, s: &'v StructDef, _: Ident, _: &'v Generics, _: NodeId) {
+    fn visit_variant_data(&mut self, s: &'v VariantData, _: Name,
+                        _: &'v Generics, _: NodeId, _: Span) {
         walk_struct_def(self, s)
     }
-    fn visit_struct_field(&mut self, s: &'v StructField) { walk_struct_field(self, s) }
-    fn visit_enum_def(&mut self, enum_definition: &'v EnumDef,
-                      generics: &'v Generics) {
-        walk_enum_def(self, enum_definition, generics)
+    fn visit_struct_field(&mut self, s: &'v StructField) {
+        walk_struct_field(self, s)
     }
-
-    fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics) { walk_variant(self, v, g) }
-
-    /// Visits an optional reference to a lifetime. The `span` is the span of some surrounding
-    /// reference should opt_lifetime be None.
-    fn visit_opt_lifetime_ref(&mut self,
-                              _span: Span,
-                              opt_lifetime: &'v Option<Lifetime>) {
-        match *opt_lifetime {
-            Some(ref l) => self.visit_lifetime_ref(l),
-            None => ()
-        }
+    fn visit_enum_def(&mut self, enum_definition: &'v EnumDef,
+                      generics: &'v Generics, item_id: NodeId, _: Span) {
+        walk_enum_def(self, enum_definition, generics, item_id)
     }
-    fn visit_lifetime_bound(&mut self, lifetime: &'v Lifetime) {
-        walk_lifetime_bound(self, lifetime)
+    fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics, item_id: NodeId) {
+        walk_variant(self, v, g, item_id)
     }
-    fn visit_lifetime_ref(&mut self, lifetime: &'v Lifetime) {
-        walk_lifetime_ref(self, lifetime)
+    fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
+        walk_lifetime(self, lifetime)
     }
     fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) {
         walk_lifetime_def(self, lifetime)
@@ -121,6 +138,9 @@ pub trait Visitor<'v> : Sized {
     fn visit_path(&mut self, path: &'v Path, _id: NodeId) {
         walk_path(self, path)
     }
+    fn visit_path_list_item(&mut self, prefix: &'v Path, item: &'v PathListItem) {
+        walk_path_list_item(self, prefix, item)
+    }
     fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
         walk_path_segment(self, path_span, path_segment)
     }
@@ -130,54 +150,74 @@ pub trait Visitor<'v> : Sized {
     fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding) {
         walk_assoc_type_binding(self, type_binding)
     }
-    fn visit_attribute(&mut self, _attr: &'v Attribute) {}
+    fn visit_attribute(&mut self, _attr: &'v Attribute) {
+    }
+    fn visit_macro_def(&mut self, macro_def: &'v MacroDef) {
+        walk_macro_def(self, macro_def)
+    }
 }
 
-pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
-    visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
-    for attr in &krate.attrs {
-        visitor.visit_attribute(attr);
+pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option<Name>) {
+    for name in opt_name {
+        visitor.visit_name(span, name);
     }
 }
 
-pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod) {
-    for item in &module.items {
-        visitor.visit_item(&**item)
+pub fn walk_opt_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_ident: Option<Ident>) {
+    for ident in opt_ident {
+        visitor.visit_ident(span, ident);
     }
 }
 
-pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
-    visitor.visit_pat(&*local.pat);
-    walk_ty_opt(visitor, &local.ty);
-    walk_expr_opt(visitor, &local.init);
+pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, ident: Ident) {
+    visitor.visit_name(span, ident.name);
 }
 
-pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V,
-                                              lifetime_def: &'v LifetimeDef) {
-    visitor.visit_name(lifetime_def.lifetime.span, lifetime_def.lifetime.name);
-    for bound in &lifetime_def.bounds {
-        visitor.visit_lifetime_bound(bound);
-    }
+pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
+    visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
+    walk_list!(visitor, visit_attribute, &krate.attrs);
+    walk_list!(visitor, visit_macro_def, &krate.exported_macros);
+}
+
+pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) {
+    visitor.visit_name(macro_def.span, macro_def.name);
+    walk_opt_name(visitor, macro_def.span, macro_def.imported_from);
+    walk_list!(visitor, visit_attribute, &macro_def.attrs);
+}
+
+pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod) {
+    walk_list!(visitor, visit_item, &module.items);
 }
 
-pub fn walk_lifetime_bound<'v, V: Visitor<'v>>(visitor: &mut V,
-                                               lifetime_ref: &'v Lifetime) {
-    visitor.visit_lifetime_ref(lifetime_ref)
+pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
+    visitor.visit_pat(&local.pat);
+    walk_list!(visitor, visit_ty, &local.ty);
+    walk_list!(visitor, visit_expr, &local.init);
+}
+
+pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
+    visitor.visit_name(lifetime.span, lifetime.name);
 }
 
-pub fn walk_lifetime_ref<'v, V: Visitor<'v>>(visitor: &mut V,
-                                             lifetime_ref: &'v Lifetime) {
-    visitor.visit_name(lifetime_ref.span, lifetime_ref.name)
+pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v LifetimeDef) {
+    visitor.visit_lifetime(&lifetime_def.lifetime);
+    walk_list!(visitor, visit_lifetime, &lifetime_def.bounds);
 }
 
-pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V,
-                                              explicit_self: &'v ExplicitSelf) {
+pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V, explicit_self: &'v ExplicitSelf) {
     match explicit_self.node {
-        SelfStatic | SelfValue(_) => {},
-        SelfRegion(ref lifetime, _, _) => {
-            visitor.visit_opt_lifetime_ref(explicit_self.span, lifetime)
+        SelfStatic => {}
+        SelfValue(name) => {
+            visitor.visit_name(explicit_self.span, name)
+        }
+        SelfRegion(ref opt_lifetime, _, name) => {
+            visitor.visit_name(explicit_self.span, name);
+            walk_list!(visitor, visit_lifetime, opt_lifetime);
+        }
+        SelfExplicit(ref typ, name) => {
+            visitor.visit_name(explicit_self.span, name);
+            visitor.visit_ty(typ)
         }
-        SelfExplicit(ref typ, _) => visitor.visit_ty(&**typ),
     }
 }
 
@@ -186,56 +226,58 @@ pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
                                   _modifier: &'v TraitBoundModifier)
     where V: Visitor<'v>
 {
-    walk_lifetime_decls_helper(visitor, &trait_ref.bound_lifetimes);
+    walk_list!(visitor,
+               visit_lifetime_def,
+               &trait_ref.bound_lifetimes);
     visitor.visit_trait_ref(&trait_ref.trait_ref);
 }
 
-pub fn walk_trait_ref<'v,V>(visitor: &mut V,
-                                   trait_ref: &'v TraitRef)
+pub fn walk_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v TraitRef)
     where V: Visitor<'v>
 {
     visitor.visit_path(&trait_ref.path, trait_ref.ref_id)
 }
 
 pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
-    visitor.visit_ident(item.span, item.ident);
+    visitor.visit_name(item.span, item.name);
     match item.node {
-        ItemExternCrate(..) => {}
+        ItemExternCrate(opt_name) => {
+            walk_opt_name(visitor, item.span, opt_name)
+        }
         ItemUse(ref vp) => {
             match vp.node {
-                ViewPathSimple(ident, ref path) => {
-                    visitor.visit_ident(vp.span, ident);
+                ViewPathSimple(name, ref path) => {
+                    visitor.visit_name(vp.span, name);
                     visitor.visit_path(path, item.id);
                 }
                 ViewPathGlob(ref path) => {
                     visitor.visit_path(path, item.id);
                 }
                 ViewPathList(ref prefix, ref list) => {
-                    for id in list {
-                        match id.node {
-                            PathListIdent { name, .. } => {
-                                visitor.visit_ident(id.span, name);
-                            }
-                            PathListMod { .. } => ()
+                    if !list.is_empty() {
+                        for item in list {
+                            visitor.visit_path_list_item(prefix, item)
                         }
+                    } else {
+                        visitor.visit_path(prefix, item.id);
                     }
-
-                    // Note that the `prefix` here is not a complete
-                    // path, so we don't use `visit_path`.
-                    walk_path(visitor, prefix);
                 }
             }
         }
         ItemStatic(ref typ, _, ref expr) |
         ItemConst(ref typ, ref expr) => {
-            visitor.visit_ty(&**typ);
-            visitor.visit_expr(&**expr);
+            visitor.visit_ty(typ);
+            visitor.visit_expr(expr);
         }
         ItemFn(ref declaration, unsafety, constness, abi, ref generics, ref body) => {
-            visitor.visit_fn(FnKind::ItemFn(item.ident, generics, unsafety,
-                                            constness, abi, item.vis),
-                             &**declaration,
-                             &**body,
+            visitor.visit_fn(FnKind::ItemFn(item.name,
+                                            generics,
+                                            unsafety,
+                                            constness,
+                                            abi,
+                                            item.vis),
+                             declaration,
+                             body,
                              item.span,
                              item.id)
         }
@@ -243,125 +285,81 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_mod(module, item.span, item.id)
         }
         ItemForeignMod(ref foreign_module) => {
-            for foreign_item in &foreign_module.items {
-                visitor.visit_foreign_item(&**foreign_item)
-            }
+            walk_list!(visitor, visit_foreign_item, &foreign_module.items);
         }
         ItemTy(ref typ, ref type_parameters) => {
-            visitor.visit_ty(&**typ);
+            visitor.visit_ty(typ);
             visitor.visit_generics(type_parameters)
         }
         ItemEnum(ref enum_definition, ref type_parameters) => {
             visitor.visit_generics(type_parameters);
-            visitor.visit_enum_def(enum_definition, type_parameters)
+            visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
         }
         ItemDefaultImpl(_, ref trait_ref) => {
             visitor.visit_trait_ref(trait_ref)
         }
         ItemImpl(_, _,
                  ref type_parameters,
-                 ref trait_reference,
+                 ref opt_trait_reference,
                  ref typ,
                  ref impl_items) => {
             visitor.visit_generics(type_parameters);
-            match *trait_reference {
-                Some(ref trait_reference) => visitor.visit_trait_ref(trait_reference),
-                None => ()
-            }
-            visitor.visit_ty(&**typ);
-            for impl_item in impl_items {
-                visitor.visit_impl_item(impl_item);
-            }
+            walk_list!(visitor, visit_trait_ref, opt_trait_reference);
+            visitor.visit_ty(typ);
+            walk_list!(visitor, visit_impl_item, impl_items);
         }
         ItemStruct(ref struct_definition, ref generics) => {
             visitor.visit_generics(generics);
-            visitor.visit_struct_def(&**struct_definition,
-                                     item.ident,
-                                     generics,
-                                     item.id)
+            visitor.visit_variant_data(struct_definition, item.name,
+                                     generics, item.id, item.span);
         }
         ItemTrait(_, ref generics, ref bounds, ref methods) => {
             visitor.visit_generics(generics);
-            walk_ty_param_bounds_helper(visitor, bounds);
-            for method in methods {
-                visitor.visit_trait_item(method)
-            }
+            walk_list!(visitor, visit_ty_param_bound, bounds);
+            walk_list!(visitor, visit_trait_item, methods);
         }
     }
-    for attr in &item.attrs {
-        visitor.visit_attribute(attr);
-    }
+    walk_list!(visitor, visit_attribute, &item.attrs);
 }
 
 pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V,
                                          enum_definition: &'v EnumDef,
-                                         generics: &'v Generics) {
-    for variant in &enum_definition.variants {
-        visitor.visit_variant(&**variant, generics);
-    }
+                                         generics: &'v Generics,
+                                         item_id: NodeId) {
+    walk_list!(visitor, visit_variant, &enum_definition.variants, generics, item_id);
 }
 
 pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
                                         variant: &'v Variant,
-                                        generics: &'v Generics) {
-    visitor.visit_ident(variant.span, variant.node.name);
-
-    match variant.node.kind {
-        TupleVariantKind(ref variant_arguments) => {
-            for variant_argument in variant_arguments {
-                visitor.visit_ty(&*variant_argument.ty)
-            }
-        }
-        StructVariantKind(ref struct_definition) => {
-            visitor.visit_struct_def(&**struct_definition,
-                                     variant.node.name,
-                                     generics,
-                                     variant.node.id)
-        }
-    }
-    match variant.node.disr_expr {
-        Some(ref expr) => visitor.visit_expr(&**expr),
-        None => ()
-    }
-    for attr in &variant.node.attrs {
-        visitor.visit_attribute(attr);
-    }
-}
-
-pub fn skip_ty<'v, V: Visitor<'v>>(_: &mut V, _: &'v Ty) {
-    // Empty!
-}
-
-pub fn walk_ty_opt<'v, V: Visitor<'v>>(visitor: &mut V, optional_type: &'v Option<P<Ty>>) {
-    match *optional_type {
-        Some(ref ty) => visitor.visit_ty(&**ty),
-        None => ()
-    }
+                                        generics: &'v Generics,
+                                        item_id: NodeId) {
+    visitor.visit_name(variant.span, variant.node.name);
+    visitor.visit_variant_data(&variant.node.data, variant.node.name,
+                             generics, item_id, variant.span);
+    walk_list!(visitor, visit_expr, &variant.node.disr_expr);
+    walk_list!(visitor, visit_attribute, &variant.node.attrs);
 }
 
 pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
     match typ.node {
         TyVec(ref ty) | TyParen(ref ty) => {
-            visitor.visit_ty(&**ty)
+            visitor.visit_ty(ty)
         }
         TyPtr(ref mutable_type) => {
-            visitor.visit_ty(&*mutable_type.ty)
+            visitor.visit_ty(&mutable_type.ty)
         }
-        TyRptr(ref lifetime, ref mutable_type) => {
-            visitor.visit_opt_lifetime_ref(typ.span, lifetime);
-            visitor.visit_ty(&*mutable_type.ty)
+        TyRptr(ref opt_lifetime, ref mutable_type) => {
+            walk_list!(visitor, visit_lifetime, opt_lifetime);
+            visitor.visit_ty(&mutable_type.ty)
         }
         TyTup(ref tuple_element_types) => {
-            for tuple_element_type in tuple_element_types {
-                visitor.visit_ty(&**tuple_element_type)
-            }
+            walk_list!(visitor, visit_ty, tuple_element_types);
         }
         TyBareFn(ref function_declaration) => {
-            for argument in &function_declaration.decl.inputs {
-                visitor.visit_ty(&*argument.ty)
-            }
-            walk_fn_ret_ty(visitor, &function_declaration.decl.output);
-            walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
+            walk_fn_decl(visitor, &function_declaration.decl);
+            walk_list!(visitor,
+                       visit_lifetime_def,
+                       &function_declaration.lifetimes);
         }
         TyPath(ref maybe_qself, ref path) => {
             if let Some(ref qself) = *maybe_qself {
@@ -370,36 +368,40 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             visitor.visit_path(path, typ.id);
         }
         TyObjectSum(ref ty, ref bounds) => {
-            visitor.visit_ty(&**ty);
-            walk_ty_param_bounds_helper(visitor, bounds);
+            visitor.visit_ty(ty);
+            walk_list!(visitor, visit_ty_param_bound, bounds);
         }
         TyFixedLengthVec(ref ty, ref expression) => {
-            visitor.visit_ty(&**ty);
-            visitor.visit_expr(&**expression)
+            visitor.visit_ty(ty);
+            visitor.visit_expr(expression)
         }
         TyPolyTraitRef(ref bounds) => {
-            walk_ty_param_bounds_helper(visitor, bounds)
+            walk_list!(visitor, visit_ty_param_bound, bounds);
         }
         TyTypeof(ref expression) => {
-            visitor.visit_expr(&**expression)
+            visitor.visit_expr(expression)
         }
         TyInfer => {}
     }
 }
 
-pub fn walk_lifetime_decls_helper<'v, V: Visitor<'v>>(visitor: &mut V,
-                                                      lifetimes: &'v Vec<LifetimeDef>) {
-    for l in lifetimes {
-        visitor.visit_lifetime_def(l);
-    }
-}
-
 pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
     for segment in &path.segments {
         visitor.visit_path_segment(path.span, segment);
     }
 }
 
+pub fn walk_path_list_item<'v, V: Visitor<'v>>(visitor: &mut V,
+                                               prefix: &'v Path,
+                                               item: &'v PathListItem) {
+    for segment in &prefix.segments {
+        visitor.visit_path_segment(prefix.span, segment);
+    }
+
+    walk_opt_name(visitor, item.span, item.node.name());
+    walk_opt_name(visitor, item.span, item.node.rename());
+}
+
 pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
                                              path_span: Span,
                                              segment: &'v PathSegment) {
@@ -411,42 +413,30 @@ pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
                                                 _path_span: Span,
                                                 path_parameters: &'v PathParameters) {
     match *path_parameters {
-        hir::AngleBracketedParameters(ref data) => {
-            for typ in data.types.iter() {
-                visitor.visit_ty(&**typ);
-            }
-            for lifetime in &data.lifetimes {
-                visitor.visit_lifetime_ref(lifetime);
-            }
-            for binding in data.bindings.iter() {
-                visitor.visit_assoc_type_binding(&**binding);
-            }
+        AngleBracketedParameters(ref data) => {
+            walk_list!(visitor, visit_ty, &data.types);
+            walk_list!(visitor, visit_lifetime, &data.lifetimes);
+            walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
         }
-        hir::ParenthesizedParameters(ref data) => {
-            for typ in &data.inputs {
-                visitor.visit_ty(&**typ);
-            }
-            if let Some(ref typ) = data.output {
-                visitor.visit_ty(&**typ);
-            }
+        ParenthesizedParameters(ref data) => {
+            walk_list!(visitor, visit_ty, &data.inputs);
+            walk_list!(visitor, visit_ty, &data.output);
         }
     }
 }
 
 pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
                                                    type_binding: &'v TypeBinding) {
-    visitor.visit_ident(type_binding.span, type_binding.ident);
-    visitor.visit_ty(&*type_binding.ty);
+    visitor.visit_name(type_binding.span, type_binding.name);
+    visitor.visit_ty(&type_binding.ty);
 }
 
 pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
     match pattern.node {
-        PatEnum(ref path, ref children) => {
+        PatEnum(ref path, ref opt_children) => {
             visitor.visit_path(path, pattern.id);
-            if let Some(ref children) = *children {
-                for child in children {
-                    visitor.visit_pat(&*child)
-                }
+            if let Some(ref children) = *opt_children {
+                walk_list!(visitor, visit_pat, children);
             }
         }
         PatQPath(ref qself, ref path) => {
@@ -456,111 +446,89 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
         PatStruct(ref path, ref fields, _) => {
             visitor.visit_path(path, pattern.id);
             for field in fields {
-                visitor.visit_pat(&*field.node.pat)
+                visitor.visit_name(field.span, field.node.name);
+                visitor.visit_pat(&field.node.pat)
             }
         }
         PatTup(ref tuple_elements) => {
-            for tuple_element in tuple_elements {
-                visitor.visit_pat(&**tuple_element)
-            }
+            walk_list!(visitor, visit_pat, tuple_elements);
         }
         PatBox(ref subpattern) |
         PatRegion(ref subpattern, _) => {
-            visitor.visit_pat(&**subpattern)
+            visitor.visit_pat(subpattern)
         }
         PatIdent(_, ref pth1, ref optional_subpattern) => {
             visitor.visit_ident(pth1.span, pth1.node);
-            match *optional_subpattern {
-                None => {}
-                Some(ref subpattern) => visitor.visit_pat(&**subpattern),
-            }
+            walk_list!(visitor, visit_pat, optional_subpattern);
         }
-        PatLit(ref expression) => visitor.visit_expr(&**expression),
+        PatLit(ref expression) => visitor.visit_expr(expression),
         PatRange(ref lower_bound, ref upper_bound) => {
-            visitor.visit_expr(&**lower_bound);
-            visitor.visit_expr(&**upper_bound)
+            visitor.visit_expr(lower_bound);
+            visitor.visit_expr(upper_bound)
         }
         PatWild(_) => (),
-        PatVec(ref prepattern, ref slice_pattern, ref postpatterns) => {
-            for prepattern in prepattern {
-                visitor.visit_pat(&**prepattern)
-            }
-            if let Some(ref slice_pattern) = *slice_pattern {
-                visitor.visit_pat(&**slice_pattern)
-            }
-            for postpattern in postpatterns {
-                visitor.visit_pat(&**postpattern)
-            }
+        PatVec(ref prepatterns, ref slice_pattern, ref postpatterns) => {
+            walk_list!(visitor, visit_pat, prepatterns);
+            walk_list!(visitor, visit_pat, slice_pattern);
+            walk_list!(visitor, visit_pat, postpatterns);
         }
     }
 }
 
-pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V,
-                                             foreign_item: &'v ForeignItem) {
-    visitor.visit_ident(foreign_item.span, foreign_item.ident);
+pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v ForeignItem) {
+    visitor.visit_name(foreign_item.span, foreign_item.name);
 
     match foreign_item.node {
         ForeignItemFn(ref function_declaration, ref generics) => {
-            walk_fn_decl(visitor, &**function_declaration);
+            walk_fn_decl(visitor, function_declaration);
             visitor.visit_generics(generics)
         }
-        ForeignItemStatic(ref typ, _) => visitor.visit_ty(&**typ),
+        ForeignItemStatic(ref typ, _) => visitor.visit_ty(typ),
     }
 
-    for attr in &foreign_item.attrs {
-        visitor.visit_attribute(attr);
-    }
+    walk_list!(visitor, visit_attribute, &foreign_item.attrs);
 }
 
-pub fn walk_ty_param_bounds_helper<'v, V: Visitor<'v>>(visitor: &mut V,
-                                                       bounds: &'v OwnedSlice<TyParamBound>) {
-    for bound in bounds.iter() {
-        visitor.visit_ty_param_bound(bound)
-    }
-}
-
-pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V,
-                                               bound: &'v TyParamBound) {
+pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyParamBound) {
     match *bound {
         TraitTyParamBound(ref typ, ref modifier) => {
             visitor.visit_poly_trait_ref(typ, modifier);
         }
         RegionTyParamBound(ref lifetime) => {
-            visitor.visit_lifetime_bound(lifetime);
+            visitor.visit_lifetime(lifetime);
         }
     }
 }
 
 pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
-    for param in generics.ty_params.iter() {
-        visitor.visit_ident(param.span, param.ident);
-        walk_ty_param_bounds_helper(visitor, &param.bounds);
-        walk_ty_opt(visitor, &param.default);
+    for param in &generics.ty_params {
+        visitor.visit_name(param.span, param.name);
+        walk_list!(visitor, visit_ty_param_bound, &param.bounds);
+        walk_list!(visitor, visit_ty, &param.default);
     }
-    walk_lifetime_decls_helper(visitor, &generics.lifetimes);
+    walk_list!(visitor, visit_lifetime_def, &generics.lifetimes);
     for predicate in &generics.where_clause.predicates {
         match predicate {
-            &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate{ref bounded_ty,
+            &WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty,
                                                                           ref bounds,
+                                                                          ref bound_lifetimes,
                                                                           ..}) => {
-                visitor.visit_ty(&**bounded_ty);
-                walk_ty_param_bounds_helper(visitor, bounds);
+                visitor.visit_ty(bounded_ty);
+                walk_list!(visitor, visit_ty_param_bound, bounds);
+                walk_list!(visitor, visit_lifetime_def, bound_lifetimes);
             }
-            &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate{ref lifetime,
+            &WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
                                                                             ref bounds,
                                                                             ..}) => {
-                visitor.visit_lifetime_ref(lifetime);
-
-                for bound in bounds {
-                    visitor.visit_lifetime_ref(bound);
-                }
+                visitor.visit_lifetime(lifetime);
+                walk_list!(visitor, visit_lifetime, bounds);
             }
-            &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{id,
+            &WherePredicate::EqPredicate(WhereEqPredicate{id,
                                                                     ref path,
                                                                     ref ty,
                                                                     ..}) => {
                 visitor.visit_path(path, id);
-                visitor.visit_ty(&**ty);
+                visitor.visit_ty(ty);
             }
         }
     }
@@ -568,20 +536,26 @@ pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics
 
 pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionRetTy) {
     if let Return(ref output_ty) = *ret_ty {
-        visitor.visit_ty(&**output_ty)
+        visitor.visit_ty(output_ty)
     }
 }
 
 pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
     for argument in &function_declaration.inputs {
-        visitor.visit_pat(&*argument.pat);
-        visitor.visit_ty(&*argument.ty)
+        visitor.visit_pat(&argument.pat);
+        visitor.visit_ty(&argument.ty)
     }
     walk_fn_ret_ty(visitor, &function_declaration.output)
 }
 
-pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V,
-                                        function_kind: FnKind<'v>) {
+pub fn walk_fn_decl_nopat<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
+    for argument in &function_declaration.inputs {
+        visitor.visit_ty(&argument.ty)
+    }
+    walk_fn_ret_ty(visitor, &function_declaration.output)
+}
+
+pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>) {
     match function_kind {
         FnKind::ItemFn(_, generics, _, _, _, _) => {
             visitor.visit_generics(generics);
@@ -590,7 +564,7 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V,
             visitor.visit_generics(&sig.generics);
             visitor.visit_explicit_self(&sig.explicit_self);
         }
-        FnKind::Closure(..) => {}
+        FnKind::Closure => {}
     }
 }
 
@@ -605,16 +579,12 @@ pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
 }
 
 pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) {
-    visitor.visit_ident(trait_item.span, trait_item.ident);
-    for attr in &trait_item.attrs {
-        visitor.visit_attribute(attr);
-    }
+    visitor.visit_name(trait_item.span, trait_item.name);
+    walk_list!(visitor, visit_attribute, &trait_item.attrs);
     match trait_item.node {
         ConstTraitItem(ref ty, ref default) => {
             visitor.visit_ty(ty);
-            if let Some(ref expr) = *default {
-                visitor.visit_expr(expr);
-            }
+            walk_list!(visitor, visit_expr, default);
         }
         MethodTraitItem(ref sig, None) => {
             visitor.visit_explicit_self(&sig.explicit_self);
@@ -622,29 +592,33 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
             walk_fn_decl(visitor, &sig.decl);
         }
         MethodTraitItem(ref sig, Some(ref body)) => {
-            visitor.visit_fn(FnKind::Method(trait_item.ident, sig, None), &sig.decl,
-                             body, trait_item.span, trait_item.id);
+            visitor.visit_fn(FnKind::Method(trait_item.name, sig, None),
+                             &sig.decl,
+                             body,
+                             trait_item.span,
+                             trait_item.id);
         }
         TypeTraitItem(ref bounds, ref default) => {
-            walk_ty_param_bounds_helper(visitor, bounds);
-            walk_ty_opt(visitor, default);
+            walk_list!(visitor, visit_ty_param_bound, bounds);
+            walk_list!(visitor, visit_ty, default);
         }
     }
 }
 
 pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
-    visitor.visit_ident(impl_item.span, impl_item.ident);
-    for attr in &impl_item.attrs {
-        visitor.visit_attribute(attr);
-    }
+    visitor.visit_name(impl_item.span, impl_item.name);
+    walk_list!(visitor, visit_attribute, &impl_item.attrs);
     match impl_item.node {
         ConstImplItem(ref ty, ref expr) => {
             visitor.visit_ty(ty);
             visitor.visit_expr(expr);
         }
         MethodImplItem(ref sig, ref body) => {
-            visitor.visit_fn(FnKind::Method(impl_item.ident, sig, Some(impl_item.vis)), &sig.decl,
-                             body, impl_item.span, impl_item.id);
+            visitor.visit_fn(FnKind::Method(impl_item.name, sig, Some(impl_item.vis)),
+                             &sig.decl,
+                             body,
+                             impl_item.span,
+                             impl_item.id);
         }
         TypeImplItem(ref ty) => {
             visitor.visit_ty(ty);
@@ -652,157 +626,129 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
     }
 }
 
-pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V,
-                                           struct_definition: &'v StructDef) {
-    for field in &struct_definition.fields {
-        visitor.visit_struct_field(field)
-    }
+pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, struct_definition: &'v VariantData) {
+    walk_list!(visitor, visit_struct_field, struct_definition.fields());
 }
 
-pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V,
-                                             struct_field: &'v StructField) {
-    if let NamedField(name, _) = struct_field.node.kind {
-        visitor.visit_ident(struct_field.span, name);
-    }
-
-    visitor.visit_ty(&*struct_field.node.ty);
-
-    for attr in &struct_field.node.attrs {
-        visitor.visit_attribute(attr);
-    }
+pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField) {
+    walk_opt_name(visitor, struct_field.span, struct_field.node.name());
+    visitor.visit_ty(&struct_field.node.ty);
+    walk_list!(visitor, visit_attribute, &struct_field.node.attrs);
 }
 
 pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) {
-    for statement in &block.stmts {
-        visitor.visit_stmt(&**statement)
-    }
-    walk_expr_opt(visitor, &block.expr)
+    walk_list!(visitor, visit_stmt, &block.stmts);
+    walk_list!(visitor, visit_expr, &block.expr);
 }
 
 pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) {
     match statement.node {
-        StmtDecl(ref declaration, _) => visitor.visit_decl(&**declaration),
+        StmtDecl(ref declaration, _) => visitor.visit_decl(declaration),
         StmtExpr(ref expression, _) | StmtSemi(ref expression, _) => {
-            visitor.visit_expr(&**expression)
+            visitor.visit_expr(expression)
         }
     }
 }
 
 pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) {
     match declaration.node {
-        DeclLocal(ref local) => visitor.visit_local(&**local),
-        DeclItem(ref item) => visitor.visit_item(&**item),
-    }
-}
-
-pub fn walk_expr_opt<'v, V: Visitor<'v>>(visitor: &mut V,
-                                         optional_expression: &'v Option<P<Expr>>) {
-    match *optional_expression {
-        None => {}
-        Some(ref expression) => visitor.visit_expr(&**expression),
-    }
-}
-
-pub fn walk_exprs<'v, V: Visitor<'v>>(visitor: &mut V, expressions: &'v [P<Expr>]) {
-    for expression in expressions {
-        visitor.visit_expr(&**expression)
+        DeclLocal(ref local) => visitor.visit_local(local),
+        DeclItem(ref item) => visitor.visit_item(item),
     }
 }
 
 pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
     match expression.node {
-        ExprBox(ref place, ref subexpression) => {
-            place.as_ref().map(|e|visitor.visit_expr(&**e));
-            visitor.visit_expr(&**subexpression)
+        ExprBox(ref subexpression) => {
+            visitor.visit_expr(subexpression)
         }
         ExprVec(ref subexpressions) => {
-            walk_exprs(visitor, subexpressions)
+            walk_list!(visitor, visit_expr, subexpressions);
         }
         ExprRepeat(ref element, ref count) => {
-            visitor.visit_expr(&**element);
-            visitor.visit_expr(&**count)
+            visitor.visit_expr(element);
+            visitor.visit_expr(count)
         }
         ExprStruct(ref path, ref fields, ref optional_base) => {
             visitor.visit_path(path, expression.id);
             for field in fields {
-                visitor.visit_expr(&*field.expr)
+                visitor.visit_name(field.name.span, field.name.node);
+                visitor.visit_expr(&field.expr)
             }
-            walk_expr_opt(visitor, optional_base)
+            walk_list!(visitor, visit_expr, optional_base);
         }
         ExprTup(ref subexpressions) => {
-            for subexpression in subexpressions {
-                visitor.visit_expr(&**subexpression)
-            }
+            walk_list!(visitor, visit_expr, subexpressions);
         }
         ExprCall(ref callee_expression, ref arguments) => {
-            for argument in arguments {
-                visitor.visit_expr(&**argument)
-            }
-            visitor.visit_expr(&**callee_expression)
+            walk_list!(visitor, visit_expr, arguments);
+            visitor.visit_expr(callee_expression)
         }
-        ExprMethodCall(_, ref types, ref arguments) => {
-            walk_exprs(visitor, arguments);
-            for typ in types {
-                visitor.visit_ty(&**typ)
-            }
+        ExprMethodCall(ref name, ref types, ref arguments) => {
+            visitor.visit_name(name.span, name.node);
+            walk_list!(visitor, visit_expr, arguments);
+            walk_list!(visitor, visit_ty, types);
         }
         ExprBinary(_, ref left_expression, ref right_expression) => {
-            visitor.visit_expr(&**left_expression);
-            visitor.visit_expr(&**right_expression)
+            visitor.visit_expr(left_expression);
+            visitor.visit_expr(right_expression)
         }
         ExprAddrOf(_, ref subexpression) | ExprUnary(_, ref subexpression) => {
-            visitor.visit_expr(&**subexpression)
+            visitor.visit_expr(subexpression)
         }
         ExprLit(_) => {}
         ExprCast(ref subexpression, ref typ) => {
-            visitor.visit_expr(&**subexpression);
-            visitor.visit_ty(&**typ)
+            visitor.visit_expr(subexpression);
+            visitor.visit_ty(typ)
         }
         ExprIf(ref head_expression, ref if_block, ref optional_else) => {
-            visitor.visit_expr(&**head_expression);
-            visitor.visit_block(&**if_block);
-            walk_expr_opt(visitor, optional_else)
+            visitor.visit_expr(head_expression);
+            visitor.visit_block(if_block);
+            walk_list!(visitor, visit_expr, optional_else);
         }
-        ExprWhile(ref subexpression, ref block, _) => {
-            visitor.visit_expr(&**subexpression);
-            visitor.visit_block(&**block)
+        ExprWhile(ref subexpression, ref block, opt_ident) => {
+            visitor.visit_expr(subexpression);
+            visitor.visit_block(block);
+            walk_opt_ident(visitor, expression.span, opt_ident)
+        }
+        ExprLoop(ref block, opt_ident) => {
+            visitor.visit_block(block);
+            walk_opt_ident(visitor, expression.span, opt_ident)
         }
-        ExprLoop(ref block, _) => visitor.visit_block(&**block),
         ExprMatch(ref subexpression, ref arms, _) => {
-            visitor.visit_expr(&**subexpression);
-            for arm in arms {
-                visitor.visit_arm(arm)
-            }
+            visitor.visit_expr(subexpression);
+            walk_list!(visitor, visit_arm, arms);
         }
         ExprClosure(_, ref function_declaration, ref body) => {
             visitor.visit_fn(FnKind::Closure,
-                             &**function_declaration,
-                             &**body,
+                             function_declaration,
+                             body,
                              expression.span,
                              expression.id)
         }
-        ExprBlock(ref block) => visitor.visit_block(&**block),
+        ExprBlock(ref block) => visitor.visit_block(block),
         ExprAssign(ref left_hand_expression, ref right_hand_expression) => {
-            visitor.visit_expr(&**right_hand_expression);
-            visitor.visit_expr(&**left_hand_expression)
+            visitor.visit_expr(right_hand_expression);
+            visitor.visit_expr(left_hand_expression)
         }
         ExprAssignOp(_, ref left_expression, ref right_expression) => {
-            visitor.visit_expr(&**right_expression);
-            visitor.visit_expr(&**left_expression)
+            visitor.visit_expr(right_expression);
+            visitor.visit_expr(left_expression)
         }
-        ExprField(ref subexpression, _) => {
-            visitor.visit_expr(&**subexpression);
+        ExprField(ref subexpression, ref name) => {
+            visitor.visit_expr(subexpression);
+            visitor.visit_name(name.span, name.node);
         }
         ExprTupField(ref subexpression, _) => {
-            visitor.visit_expr(&**subexpression);
+            visitor.visit_expr(subexpression);
         }
         ExprIndex(ref main_expression, ref index_expression) => {
-            visitor.visit_expr(&**main_expression);
-            visitor.visit_expr(&**index_expression)
+            visitor.visit_expr(main_expression);
+            visitor.visit_expr(index_expression)
         }
         ExprRange(ref start, ref end) => {
-            walk_expr_opt(visitor, start);
-            walk_expr_opt(visitor, end)
+            walk_list!(visitor, visit_expr, start);
+            walk_list!(visitor, visit_expr, end);
         }
         ExprPath(ref maybe_qself, ref path) => {
             if let Some(ref qself) = *maybe_qself {
@@ -810,21 +756,20 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             }
             visitor.visit_path(path, expression.id)
         }
-        ExprBreak(_) | ExprAgain(_) => {}
-        ExprRet(ref optional_expression) => {
-            walk_expr_opt(visitor, optional_expression)
+        ExprBreak(ref opt_sp_ident) | ExprAgain(ref opt_sp_ident) => {
+            for sp_ident in opt_sp_ident {
+                visitor.visit_ident(sp_ident.span, sp_ident.node);
+            }
         }
-        ExprParen(ref subexpression) => {
-            visitor.visit_expr(&**subexpression)
+        ExprRet(ref optional_expression) => {
+            walk_list!(visitor, visit_expr, optional_expression);
         }
         ExprInlineAsm(ref ia) => {
-            for input in &ia.inputs {
-                let (_, ref input) = *input;
-                visitor.visit_expr(&**input)
+            for &(_, ref input) in &ia.inputs {
+                visitor.visit_expr(&input)
             }
-            for output in &ia.outputs {
-                let (_, ref output, _) = *output;
-                visitor.visit_expr(&**output)
+            for &(_, ref output, _) in &ia.outputs {
+                visitor.visit_expr(&output)
             }
         }
     }
@@ -833,12 +778,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
 }
 
 pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
-    for pattern in &arm.pats {
-        visitor.visit_pat(&**pattern)
-    }
-    walk_expr_opt(visitor, &arm.guard);
-    visitor.visit_expr(&*arm.body);
-    for attr in &arm.attrs {
-        visitor.visit_attribute(attr);
-    }
+    walk_list!(visitor, visit_pat, &arm.pats);
+    walk_list!(visitor, visit_expr, &arm.guard);
+    visitor.visit_expr(&arm.body);
+    walk_list!(visitor, visit_attribute, &arm.attrs);
 }
diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs
new file mode 100644 (file)
index 0000000..693de17
--- /dev/null
@@ -0,0 +1,372 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use middle::def;
+use middle::ty;
+use lint::{LateContext, LintContext, LintArray};
+use lint::{LintPass, LateLintPass};
+
+use syntax::ast;
+use syntax::attr::{self, AttrMetaMethods};
+use syntax::codemap::Span;
+
+use rustc_front::hir;
+use rustc_front::visit::FnKind;
+
+#[derive(PartialEq)]
+pub enum MethodLateContext {
+    TraitDefaultImpl,
+    TraitImpl,
+    PlainImpl
+}
+
+pub fn method_context(cx: &LateContext, id: ast::NodeId, span: Span) -> MethodLateContext {
+    let def_id = cx.tcx.map.local_def_id(id);
+    match cx.tcx.impl_or_trait_items.borrow().get(&def_id) {
+        None => cx.sess().span_bug(span, "missing method descriptor?!"),
+        Some(item) => match item.container() {
+            ty::TraitContainer(..) => MethodLateContext::TraitDefaultImpl,
+            ty::ImplContainer(cid) => {
+                match cx.tcx.impl_trait_ref(cid) {
+                    Some(_) => MethodLateContext::TraitImpl,
+                    None => MethodLateContext::PlainImpl
+                }
+            }
+        }
+    }
+}
+
+declare_lint! {
+    pub NON_CAMEL_CASE_TYPES,
+    Warn,
+    "types, variants, traits and type parameters should have camel case names"
+}
+
+#[derive(Copy, Clone)]
+pub struct NonCamelCaseTypes;
+
+impl NonCamelCaseTypes {
+    fn check_case(&self, cx: &LateContext, sort: &str, name: ast::Name, span: Span) {
+        fn is_camel_case(name: ast::Name) -> bool {
+            let name = name.as_str();
+            if name.is_empty() {
+                return true;
+            }
+            let name = name.trim_matches('_');
+
+            // start with a non-lowercase letter rather than non-uppercase
+            // ones (some scripts don't have a concept of upper/lowercase)
+            !name.is_empty() && !name.char_at(0).is_lowercase() && !name.contains('_')
+        }
+
+        fn to_camel_case(s: &str) -> String {
+            s.split('_').flat_map(|word| word.chars().enumerate().map(|(i, c)|
+                if i == 0 {
+                    c.to_uppercase().collect::<String>()
+                } else {
+                    c.to_lowercase().collect()
+                }
+            )).collect::<Vec<_>>().concat()
+        }
+
+        let s = name.as_str();
+
+        if !is_camel_case(name) {
+            let c = to_camel_case(&s);
+            let m = if c.is_empty() {
+                format!("{} `{}` should have a camel case name such as `CamelCase`", sort, s)
+            } else {
+                format!("{} `{}` should have a camel case name such as `{}`", sort, s, c)
+            };
+            cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m[..]);
+        }
+    }
+}
+
+impl LintPass for NonCamelCaseTypes {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(NON_CAMEL_CASE_TYPES)
+    }
+}
+
+impl LateLintPass for NonCamelCaseTypes {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+        let extern_repr_count = it.attrs.iter().filter(|attr| {
+            attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr).iter()
+                .any(|r| r == &attr::ReprExtern)
+        }).count();
+        let has_extern_repr = extern_repr_count > 0;
+
+        if has_extern_repr {
+            return;
+        }
+
+        match it.node {
+            hir::ItemTy(..) | hir::ItemStruct(..) => {
+                self.check_case(cx, "type", it.name, it.span)
+            }
+            hir::ItemTrait(..) => {
+                self.check_case(cx, "trait", it.name, it.span)
+            }
+            hir::ItemEnum(ref enum_definition, _) => {
+                if has_extern_repr {
+                    return;
+                }
+                self.check_case(cx, "type", it.name, it.span);
+                for variant in &enum_definition.variants {
+                    self.check_case(cx, "variant", variant.node.name, variant.span);
+                }
+            }
+            _ => ()
+        }
+    }
+
+    fn check_generics(&mut self, cx: &LateContext, it: &hir::Generics) {
+        for gen in it.ty_params.iter() {
+            self.check_case(cx, "type parameter", gen.name, gen.span);
+        }
+    }
+}
+
+declare_lint! {
+    pub NON_SNAKE_CASE,
+    Warn,
+    "methods, functions, lifetime parameters and modules should have snake case names"
+}
+
+#[derive(Copy, Clone)]
+pub struct NonSnakeCase;
+
+impl NonSnakeCase {
+    fn to_snake_case(mut str: &str) -> String {
+        let mut words = vec![];
+        // Preserve leading underscores
+        str = str.trim_left_matches(|c: char| {
+            if c == '_' {
+                words.push(String::new());
+                true
+            } else {
+                false
+            }
+        });
+        for s in str.split('_') {
+            let mut last_upper = false;
+            let mut buf = String::new();
+            if s.is_empty() {
+                continue;
+            }
+            for ch in s.chars() {
+                if !buf.is_empty() && buf != "'"
+                                   && ch.is_uppercase()
+                                   && !last_upper {
+                    words.push(buf);
+                    buf = String::new();
+                }
+                last_upper = ch.is_uppercase();
+                buf.extend(ch.to_lowercase());
+            }
+            words.push(buf);
+        }
+        words.join("_")
+    }
+
+    fn check_snake_case(&self, cx: &LateContext, sort: &str, name: &str, span: Option<Span>) {
+        fn is_snake_case(ident: &str) -> bool {
+            if ident.is_empty() {
+                return true;
+            }
+            let ident = ident.trim_left_matches('\'');
+            let ident = ident.trim_matches('_');
+
+            let mut allow_underscore = true;
+            ident.chars().all(|c| {
+                allow_underscore = match c {
+                    '_' if !allow_underscore => return false,
+                    '_' => false,
+                    // It would be more obvious to use `c.is_lowercase()`,
+                    // but some characters do not have a lowercase form
+                    c if !c.is_uppercase() => true,
+                    _ => return false,
+                };
+                true
+            })
+        }
+
+        if !is_snake_case(name) {
+            let sc = NonSnakeCase::to_snake_case(name);
+            let msg = if sc != name {
+                format!("{} `{}` should have a snake case name such as `{}`",
+                        sort, name, sc)
+            } else {
+                format!("{} `{}` should have a snake case name",
+                        sort, name)
+            };
+            match span {
+                Some(span) => cx.span_lint(NON_SNAKE_CASE, span, &msg),
+                None => cx.lint(NON_SNAKE_CASE, &msg),
+            }
+        }
+    }
+}
+
+impl LintPass for NonSnakeCase {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(NON_SNAKE_CASE)
+    }
+}
+
+impl LateLintPass for NonSnakeCase {
+    fn check_crate(&mut self, cx: &LateContext, cr: &hir::Crate) {
+        let attr_crate_name = cr.attrs.iter().find(|at| at.check_name("crate_name"))
+                                      .and_then(|at| at.value_str().map(|s| (at, s)));
+        if let Some(ref name) = cx.tcx.sess.opts.crate_name {
+            self.check_snake_case(cx, "crate", name, None);
+        } else if let Some((attr, ref name)) = attr_crate_name {
+            self.check_snake_case(cx, "crate", name, Some(attr.span));
+        }
+    }
+
+    fn check_fn(&mut self, cx: &LateContext,
+                fk: FnKind, _: &hir::FnDecl,
+                _: &hir::Block, span: Span, id: ast::NodeId) {
+        match fk {
+            FnKind::Method(name, _, _) => match method_context(cx, id, span) {
+                MethodLateContext::PlainImpl => {
+                    self.check_snake_case(cx, "method", &name.as_str(), Some(span))
+                },
+                MethodLateContext::TraitDefaultImpl => {
+                    self.check_snake_case(cx, "trait method", &name.as_str(), Some(span))
+                },
+                _ => (),
+            },
+            FnKind::ItemFn(name, _, _, _, _, _) => {
+                self.check_snake_case(cx, "function", &name.as_str(), Some(span))
+            },
+            _ => (),
+        }
+    }
+
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+        if let hir::ItemMod(_) = it.node {
+            self.check_snake_case(cx, "module", &it.name.as_str(), Some(it.span));
+        }
+    }
+
+    fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) {
+        if let hir::MethodTraitItem(_, None) = trait_item.node {
+            self.check_snake_case(cx, "trait method", &trait_item.name.as_str(),
+                                  Some(trait_item.span));
+        }
+    }
+
+    fn check_lifetime_def(&mut self, cx: &LateContext, t: &hir::LifetimeDef) {
+        self.check_snake_case(cx, "lifetime", &t.lifetime.name.as_str(),
+                              Some(t.lifetime.span));
+    }
+
+    fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
+        if let &hir::PatIdent(_, ref path1, _) = &p.node {
+            let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
+            if let Some(def::DefLocal(..)) = def {
+                self.check_snake_case(cx, "variable", &path1.node.name.as_str(), Some(p.span));
+            }
+        }
+    }
+
+    fn check_struct_def(&mut self, cx: &LateContext, s: &hir::VariantData,
+                        _: ast::Name, _: &hir::Generics, _: ast::NodeId) {
+        for sf in s.fields() {
+            if let hir::StructField_ { kind: hir::NamedField(name, _), .. } = sf.node {
+                self.check_snake_case(cx, "structure field", &name.as_str(),
+                                      Some(sf.span));
+            }
+        }
+    }
+}
+
+declare_lint! {
+    pub NON_UPPER_CASE_GLOBALS,
+    Warn,
+    "static constants should have uppercase identifiers"
+}
+
+#[derive(Copy, Clone)]
+pub struct NonUpperCaseGlobals;
+
+impl NonUpperCaseGlobals {
+    fn check_upper_case(cx: &LateContext, sort: &str, name: ast::Name, span: Span) {
+        let s = name.as_str();
+
+        if s.chars().any(|c| c.is_lowercase()) {
+            let uc = NonSnakeCase::to_snake_case(&s).to_uppercase();
+            if uc != &s[..] {
+                cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
+                    &format!("{} `{}` should have an upper case name such as `{}`",
+                             sort, s, uc));
+            } else {
+                cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
+                    &format!("{} `{}` should have an upper case name",
+                             sort, s));
+            }
+        }
+    }
+}
+
+impl LintPass for NonUpperCaseGlobals {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(NON_UPPER_CASE_GLOBALS)
+    }
+}
+
+impl LateLintPass for NonUpperCaseGlobals {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+        match it.node {
+            // only check static constants
+            hir::ItemStatic(_, hir::MutImmutable, _) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "static constant", it.name, it.span);
+            }
+            hir::ItemConst(..) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "constant", it.name, it.span);
+            }
+            _ => {}
+        }
+    }
+
+    fn check_trait_item(&mut self, cx: &LateContext, ti: &hir::TraitItem) {
+        match ti.node {
+            hir::ConstTraitItem(..) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
+                                                      ti.name, ti.span);
+            }
+            _ => {}
+        }
+    }
+
+    fn check_impl_item(&mut self, cx: &LateContext, ii: &hir::ImplItem) {
+        match ii.node {
+            hir::ConstImplItem(..) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
+                                                      ii.name, ii.span);
+            }
+            _ => {}
+        }
+    }
+
+    fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
+        // Lint for constants that look like binding identifiers (#7526)
+        match (&p.node, cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def())) {
+            (&hir::PatIdent(_, ref path1, _), Some(def::DefConst(..))) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern",
+                                                      path1.node.name, p.span);
+            }
+            _ => {}
+        }
+    }
+}
index 717690adddeddc0174cb8e50f8ba276dbb62efa3..a001289b196a9517f318c21c52a2447636cf821b 100644 (file)
 //! Use the former for unit-like structs and the latter for structs with
 //! a `pub fn new()`.
 
-use metadata::{csearch, decoder};
-use middle::{cfg, def, infer, pat_util, stability, traits};
+use metadata::decoder;
+use middle::{cfg, def, infer, stability, traits};
 use middle::def_id::DefId;
 use middle::subst::Substs;
 use middle::ty::{self, Ty};
 use middle::ty::adjustment;
-use middle::const_eval::{eval_const_expr_partial, ConstVal};
-use middle::const_eval::EvalHint::ExprTypeChecked;
 use rustc::front::map as hir_map;
-use util::nodemap::{FnvHashMap, FnvHashSet, NodeSet};
-use lint::{Level, Context, LintPass, LintArray, Lint};
+use util::nodemap::{NodeSet};
+use lint::{Level, LateContext, LintContext, LintArray, Lint};
+use lint::{LintPass, LateLintPass};
 
 use std::collections::HashSet;
-use std::collections::hash_map::Entry::{Occupied, Vacant};
-use std::{cmp, slice};
-use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
 
-use syntax::{abi, ast};
-use syntax::attr as syntax_attr;
+use syntax::{ast};
+use syntax::attr::{self, AttrMetaMethods};
 use syntax::codemap::{self, Span};
-use syntax::feature_gate::{KNOWN_ATTRIBUTES, AttributeType};
-use rustc_front::hir::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64};
-use syntax::ptr::P;
 
 use rustc_front::hir;
+use rustc_front::visit::{self, FnKind, Visitor};
 
-use rustc_front::attr::{self, AttrMetaMethods};
-use rustc_front::visit::{self, FnKind, Visitor};
-use rustc_front::lowering::unlower_attribute;
-
-use rustc_front::util::is_shift_binop;
-
-// hardwired lints from librustc
-pub use lint::builtin::*;
-
-declare_lint! {
-    WHILE_TRUE,
-    Warn,
-    "suggest using `loop { }` instead of `while true { }`"
-}
-
-#[derive(Copy, Clone)]
-pub struct WhileTrue;
-
-impl LintPass for WhileTrue {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(WHILE_TRUE)
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &hir::Expr) {
-        if let hir::ExprWhile(ref cond, _, _) = e.node {
-            if let hir::ExprLit(ref lit) = cond.node {
-                if let hir::LitBool(true) = lit.node {
-                    cx.span_lint(WHILE_TRUE, e.span,
-                                 "denote infinite loops with loop { ... }");
-                }
-            }
-        }
-    }
-}
-
-declare_lint! {
-    UNUSED_COMPARISONS,
-    Warn,
-    "comparisons made useless by limits of the types involved"
-}
-
-declare_lint! {
-    OVERFLOWING_LITERALS,
-    Warn,
-    "literal out of range for its type"
-}
-
-declare_lint! {
-    EXCEEDING_BITSHIFTS,
-    Deny,
-    "shift exceeds the type's number of bits"
-}
-
-#[derive(Copy, Clone)]
-pub struct TypeLimits {
-    /// Id of the last visited negated expression
-    negated_expr_id: ast::NodeId,
-}
-
-impl TypeLimits {
-    pub fn new() -> TypeLimits {
-        TypeLimits {
-            negated_expr_id: !0,
-        }
-    }
-}
-
-impl LintPass for TypeLimits {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_COMPARISONS, OVERFLOWING_LITERALS, EXCEEDING_BITSHIFTS)
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &hir::Expr) {
-        match e.node {
-            hir::ExprUnary(hir::UnNeg, ref expr) => {
-                match expr.node  {
-                    hir::ExprLit(ref lit) => {
-                        match lit.node {
-                            hir::LitInt(_, hir::UnsignedIntLit(_)) => {
-                                check_unsigned_negation_feature(cx, e.span);
-                            },
-                            hir::LitInt(_, hir::UnsuffixedIntLit(_)) => {
-                                if let ty::TyUint(_) = cx.tcx.node_id_to_type(e.id).sty {
-                                    check_unsigned_negation_feature(cx, e.span);
-                                }
-                            },
-                            _ => ()
-                        }
-                    },
-                    _ => {
-                        let t = cx.tcx.node_id_to_type(expr.id);
-                        match t.sty {
-                            ty::TyUint(_) => {
-                                check_unsigned_negation_feature(cx, e.span);
-                            },
-                            _ => ()
-                        }
-                    }
-                };
-                // propagate negation, if the negation itself isn't negated
-                if self.negated_expr_id != e.id {
-                    self.negated_expr_id = expr.id;
-                }
-            },
-            hir::ExprParen(ref expr) if self.negated_expr_id == e.id => {
-                self.negated_expr_id = expr.id;
-            },
-            hir::ExprBinary(binop, ref l, ref r) => {
-                if is_comparison(binop) && !check_limits(cx.tcx, binop, &**l, &**r) {
-                    cx.span_lint(UNUSED_COMPARISONS, e.span,
-                                 "comparison is useless due to type limits");
-                }
-
-                if is_shift_binop(binop.node) {
-                    let opt_ty_bits = match cx.tcx.node_id_to_type(l.id).sty {
-                        ty::TyInt(t) => Some(int_ty_bits(t, cx.sess().target.int_type)),
-                        ty::TyUint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)),
-                        _ => None
-                    };
-
-                    if let Some(bits) = opt_ty_bits {
-                        let exceeding = if let hir::ExprLit(ref lit) = r.node {
-                            if let hir::LitInt(shift, _) = lit.node { shift >= bits }
-                            else { false }
-                        } else {
-                            match eval_const_expr_partial(cx.tcx, &r, ExprTypeChecked) {
-                                Ok(ConstVal::Int(shift)) => { shift as u64 >= bits },
-                                Ok(ConstVal::Uint(shift)) => { shift >= bits },
-                                _ => { false }
-                            }
-                        };
-                        if exceeding {
-                            cx.span_lint(EXCEEDING_BITSHIFTS, e.span,
-                                         "bitshift exceeds the type's number of bits");
-                        }
-                    };
-                }
-            },
-            hir::ExprLit(ref lit) => {
-                match cx.tcx.node_id_to_type(e.id).sty {
-                    ty::TyInt(t) => {
-                        match lit.node {
-                            hir::LitInt(v, hir::SignedIntLit(_, hir::Plus)) |
-                            hir::LitInt(v, hir::UnsuffixedIntLit(hir::Plus)) => {
-                                let int_type = if let hir::TyIs = t {
-                                    cx.sess().target.int_type
-                                } else {
-                                    t
-                                };
-                                let (_, max) = int_ty_range(int_type);
-                                let negative = self.negated_expr_id == e.id;
-
-                                // Detect literal value out of range [min, max] inclusive
-                                // avoiding use of -min to prevent overflow/panic
-                                if (negative && v > max as u64 + 1) ||
-                                   (!negative && v > max as u64) {
-                                    cx.span_lint(OVERFLOWING_LITERALS, e.span,
-                                                 &*format!("literal out of range for {:?}", t));
-                                    return;
-                                }
-                            }
-                            _ => panic!()
-                        };
-                    },
-                    ty::TyUint(t) => {
-                        let uint_type = if let hir::TyUs = t {
-                            cx.sess().target.uint_type
-                        } else {
-                            t
-                        };
-                        let (min, max) = uint_ty_range(uint_type);
-                        let lit_val: u64 = match lit.node {
-                            hir::LitByte(_v) => return,  // _v is u8, within range by definition
-                            hir::LitInt(v, _) => v,
-                            _ => panic!()
-                        };
-                        if lit_val < min || lit_val > max {
-                            cx.span_lint(OVERFLOWING_LITERALS, e.span,
-                                         &*format!("literal out of range for {:?}", t));
-                        }
-                    },
-                    ty::TyFloat(t) => {
-                        let (min, max) = float_ty_range(t);
-                        let lit_val: f64 = match lit.node {
-                            hir::LitFloat(ref v, _) |
-                            hir::LitFloatUnsuffixed(ref v) => {
-                                match v.parse() {
-                                    Ok(f) => f,
-                                    Err(_) => return
-                                }
-                            }
-                            _ => panic!()
-                        };
-                        if lit_val < min || lit_val > max {
-                            cx.span_lint(OVERFLOWING_LITERALS, e.span,
-                                         &*format!("literal out of range for {:?}", t));
-                        }
-                    },
-                    _ => ()
-                };
-            },
-            _ => ()
-        };
-
-        fn is_valid<T:cmp::PartialOrd>(binop: hir::BinOp, v: T,
-                                min: T, max: T) -> bool {
-            match binop.node {
-                hir::BiLt => v >  min && v <= max,
-                hir::BiLe => v >= min && v <  max,
-                hir::BiGt => v >= min && v <  max,
-                hir::BiGe => v >  min && v <= max,
-                hir::BiEq | hir::BiNe => v >= min && v <= max,
-                _ => panic!()
-            }
-        }
-
-        fn rev_binop(binop: hir::BinOp) -> hir::BinOp {
-            codemap::respan(binop.span, match binop.node {
-                hir::BiLt => hir::BiGt,
-                hir::BiLe => hir::BiGe,
-                hir::BiGt => hir::BiLt,
-                hir::BiGe => hir::BiLe,
-                _ => return binop
-            })
-        }
-
-        // for isize & usize, be conservative with the warnings, so that the
-        // warnings are consistent between 32- and 64-bit platforms
-        fn int_ty_range(int_ty: hir::IntTy) -> (i64, i64) {
-            match int_ty {
-                hir::TyIs => (i64::MIN,        i64::MAX),
-                hir::TyI8 =>    (i8::MIN  as i64, i8::MAX  as i64),
-                hir::TyI16 =>   (i16::MIN as i64, i16::MAX as i64),
-                hir::TyI32 =>   (i32::MIN as i64, i32::MAX as i64),
-                hir::TyI64 =>   (i64::MIN,        i64::MAX)
-            }
-        }
-
-        fn uint_ty_range(uint_ty: hir::UintTy) -> (u64, u64) {
-            match uint_ty {
-                hir::TyUs => (u64::MIN,         u64::MAX),
-                hir::TyU8 =>    (u8::MIN   as u64, u8::MAX   as u64),
-                hir::TyU16 =>   (u16::MIN  as u64, u16::MAX  as u64),
-                hir::TyU32 =>   (u32::MIN  as u64, u32::MAX  as u64),
-                hir::TyU64 =>   (u64::MIN,         u64::MAX)
-            }
-        }
-
-        fn float_ty_range(float_ty: hir::FloatTy) -> (f64, f64) {
-            match float_ty {
-                hir::TyF32 => (f32::MIN as f64, f32::MAX as f64),
-                hir::TyF64 => (f64::MIN,        f64::MAX)
-            }
-        }
-
-        fn int_ty_bits(int_ty: hir::IntTy, target_int_ty: hir::IntTy) -> u64 {
-            match int_ty {
-                hir::TyIs => int_ty_bits(target_int_ty, target_int_ty),
-                hir::TyI8 =>    i8::BITS  as u64,
-                hir::TyI16 =>   i16::BITS as u64,
-                hir::TyI32 =>   i32::BITS as u64,
-                hir::TyI64 =>   i64::BITS as u64
-            }
-        }
-
-        fn uint_ty_bits(uint_ty: hir::UintTy, target_uint_ty: hir::UintTy) -> u64 {
-            match uint_ty {
-                hir::TyUs => uint_ty_bits(target_uint_ty, target_uint_ty),
-                hir::TyU8 =>    u8::BITS  as u64,
-                hir::TyU16 =>   u16::BITS as u64,
-                hir::TyU32 =>   u32::BITS as u64,
-                hir::TyU64 =>   u64::BITS as u64
-            }
-        }
-
-        fn check_limits(tcx: &ty::ctxt, binop: hir::BinOp,
-                        l: &hir::Expr, r: &hir::Expr) -> bool {
-            let (lit, expr, swap) = match (&l.node, &r.node) {
-                (&hir::ExprLit(_), _) => (l, r, true),
-                (_, &hir::ExprLit(_)) => (r, l, false),
-                _ => return true
-            };
-            // Normalize the binop so that the literal is always on the RHS in
-            // the comparison
-            let norm_binop = if swap {
-                rev_binop(binop)
-            } else {
-                binop
-            };
-            match tcx.node_id_to_type(expr.id).sty {
-                ty::TyInt(int_ty) => {
-                    let (min, max) = int_ty_range(int_ty);
-                    let lit_val: i64 = match lit.node {
-                        hir::ExprLit(ref li) => match li.node {
-                            hir::LitInt(v, hir::SignedIntLit(_, hir::Plus)) |
-                            hir::LitInt(v, hir::UnsuffixedIntLit(hir::Plus)) => v as i64,
-                            hir::LitInt(v, hir::SignedIntLit(_, hir::Minus)) |
-                            hir::LitInt(v, hir::UnsuffixedIntLit(hir::Minus)) => -(v as i64),
-                            _ => return true
-                        },
-                        _ => panic!()
-                    };
-                    is_valid(norm_binop, lit_val, min, max)
-                }
-                ty::TyUint(uint_ty) => {
-                    let (min, max): (u64, u64) = uint_ty_range(uint_ty);
-                    let lit_val: u64 = match lit.node {
-                        hir::ExprLit(ref li) => match li.node {
-                            hir::LitInt(v, _) => v,
-                            _ => return true
-                        },
-                        _ => panic!()
-                    };
-                    is_valid(norm_binop, lit_val, min, max)
-                }
-                _ => true
-            }
-        }
-
-        fn is_comparison(binop: hir::BinOp) -> bool {
-            match binop.node {
-                hir::BiEq | hir::BiLt | hir::BiLe |
-                hir::BiNe | hir::BiGe | hir::BiGt => true,
-                _ => false
-            }
-        }
-
-        fn check_unsigned_negation_feature(cx: &Context, span: Span) {
-            if !cx.sess().features.borrow().negate_unsigned {
-                // FIXME(#27141): change this to syntax::feature_gate::emit_feature_err…
-                cx.sess().span_warn(span,
-                    "unary negation of unsigned integers will be feature gated in the future");
-                // …and remove following two expressions.
-                if option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some() { return; }
-                cx.sess().fileline_help(span, "add #![feature(negate_unsigned)] to the \
-                                               crate attributes to enable the gate in advance");
-            }
-        }
-    }
-}
-
-declare_lint! {
-    IMPROPER_CTYPES,
-    Warn,
-    "proper use of libc types in foreign modules"
-}
-
-struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
-    cx: &'a Context<'a, 'tcx>
-}
-
-enum FfiResult {
-    FfiSafe,
-    FfiUnsafe(&'static str),
-    FfiBadStruct(DefId, &'static str),
-    FfiBadEnum(DefId, &'static str)
-}
-
-/// Check if this enum can be safely exported based on the
-/// "nullable pointer optimization". Currently restricted
-/// to function pointers and references, but could be
-/// expanded to cover NonZero raw pointers and newtypes.
-/// FIXME: This duplicates code in trans.
-fn is_repr_nullable_ptr<'tcx>(tcx: &ty::ctxt<'tcx>,
-                              def: ty::AdtDef<'tcx>,
-                              substs: &Substs<'tcx>)
-                              -> bool {
-    if def.variants.len() == 2 {
-        let data_idx;
-
-        if def.variants[0].fields.is_empty() {
-            data_idx = 1;
-        } else if def.variants[1].fields.is_empty() {
-            data_idx = 0;
-        } else {
-            return false;
-        }
-
-        if def.variants[data_idx].fields.len() == 1 {
-            match def.variants[data_idx].fields[0].ty(tcx, substs).sty {
-                ty::TyBareFn(None, _) => { return true; }
-                ty::TyRef(..) => { return true; }
-                _ => { }
-            }
-        }
-    }
-    false
-}
-
-fn ast_ty_to_normalized<'tcx>(tcx: &ty::ctxt<'tcx>,
-                              id: ast::NodeId)
-                              -> Ty<'tcx> {
-    let tty = match tcx.ast_ty_to_ty_cache.borrow().get(&id) {
-        Some(&t) => t,
-        None => panic!("ast_ty_to_ty_cache was incomplete after typeck!")
-    };
-    infer::normalize_associated_type(tcx, &tty)
-}
-
-impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
-    /// Check if the given type is "ffi-safe" (has a stable, well-defined
-    /// representation which can be exported to C code).
-    fn check_type_for_ffi(&self,
-                          cache: &mut FnvHashSet<Ty<'tcx>>,
-                          ty: Ty<'tcx>)
-                          -> FfiResult {
-        use self::FfiResult::*;
-        let cx = &self.cx.tcx;
-
-        // Protect against infinite recursion, for example
-        // `struct S(*mut S);`.
-        // FIXME: A recursion limit is necessary as well, for irregular
-        // recusive types.
-        if !cache.insert(ty) {
-            return FfiSafe;
-        }
-
-        match ty.sty {
-            ty::TyStruct(def, substs) => {
-                if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) {
-                    return FfiUnsafe(
-                        "found struct without foreign-function-safe \
-                         representation annotation in foreign module, \
-                         consider adding a #[repr(C)] attribute to \
-                         the type");
-                }
-
-                // We can't completely trust repr(C) markings; make sure the
-                // fields are actually safe.
-                if def.struct_variant().fields.is_empty() {
-                    return FfiUnsafe(
-                        "found zero-size struct in foreign module, consider \
-                         adding a member to this struct");
-                }
-
-                for field in &def.struct_variant().fields {
-                    let field_ty = infer::normalize_associated_type(cx, &field.ty(cx, substs));
-                    let r = self.check_type_for_ffi(cache, field_ty);
-                    match r {
-                        FfiSafe => {}
-                        FfiBadStruct(..) | FfiBadEnum(..) => { return r; }
-                        FfiUnsafe(s) => { return FfiBadStruct(def.did, s); }
-                    }
-                }
-                FfiSafe
-            }
-            ty::TyEnum(def, substs) => {
-                if def.variants.is_empty() {
-                    // Empty enums are okay... although sort of useless.
-                    return FfiSafe
-                }
-
-                // Check for a repr() attribute to specify the size of the
-                // discriminant.
-                let repr_hints = cx.lookup_repr_hints(def.did);
-                match &**repr_hints {
-                    [] => {
-                        // Special-case types like `Option<extern fn()>`.
-                        if !is_repr_nullable_ptr(cx, def, substs) {
-                            return FfiUnsafe(
-                                "found enum without foreign-function-safe \
-                                 representation annotation in foreign module, \
-                                 consider adding a #[repr(...)] attribute to \
-                                 the type")
-                        }
-                    }
-                    [ref hint] => {
-                        if !hint.is_ffi_safe() {
-                            // FIXME: This shouldn't be reachable: we should check
-                            // this earlier.
-                            return FfiUnsafe(
-                                "enum has unexpected #[repr(...)] attribute")
-                        }
-
-                        // Enum with an explicitly sized discriminant; either
-                        // a C-style enum or a discriminated union.
-
-                        // The layout of enum variants is implicitly repr(C).
-                        // FIXME: Is that correct?
-                    }
-                    _ => {
-                        // FIXME: This shouldn't be reachable: we should check
-                        // this earlier.
-                        return FfiUnsafe(
-                            "enum has too many #[repr(...)] attributes");
-                    }
-                }
-
-                // Check the contained variants.
-                for variant in &def.variants {
-                    for field in &variant.fields {
-                        let arg = infer::normalize_associated_type(cx, &field.ty(cx, substs));
-                        let r = self.check_type_for_ffi(cache, arg);
-                        match r {
-                            FfiSafe => {}
-                            FfiBadStruct(..) | FfiBadEnum(..) => { return r; }
-                            FfiUnsafe(s) => { return FfiBadEnum(def.did, s); }
-                        }
-                    }
-                }
-                FfiSafe
-            }
-
-            ty::TyChar => {
-                FfiUnsafe("found Rust type `char` in foreign module, while \
-                           `u32` or `libc::wchar_t` should be used")
-            }
-
-            // Primitive types with a stable representation.
-            ty::TyBool | ty::TyInt(..) | ty::TyUint(..) |
-            ty::TyFloat(..) => FfiSafe,
-
-            ty::TyBox(..) => {
-                FfiUnsafe("found Rust type Box<_> in foreign module, \
-                           consider using a raw pointer instead")
-            }
-
-            ty::TySlice(_) => {
-                FfiUnsafe("found Rust slice type in foreign module, \
-                           consider using a raw pointer instead")
-            }
-
-            ty::TyTrait(..) => {
-                FfiUnsafe("found Rust trait type in foreign module, \
-                           consider using a raw pointer instead")
-            }
-
-            ty::TyStr => {
-                FfiUnsafe("found Rust type `str` in foreign module; \
-                           consider using a `*const libc::c_char`")
-            }
-
-            ty::TyTuple(_) => {
-                FfiUnsafe("found Rust tuple type in foreign module; \
-                           consider using a struct instead`")
-            }
-
-            ty::TyRawPtr(ref m) | ty::TyRef(_, ref m) => {
-                self.check_type_for_ffi(cache, m.ty)
-            }
-
-            ty::TyArray(ty, _) => {
-                self.check_type_for_ffi(cache, ty)
-            }
-
-            ty::TyBareFn(None, bare_fn) => {
-                match bare_fn.abi {
-                    abi::Rust |
-                    abi::RustIntrinsic |
-                    abi::PlatformIntrinsic |
-                    abi::RustCall => {
-                        return FfiUnsafe(
-                            "found function pointer with Rust calling \
-                             convention in foreign module; consider using an \
-                             `extern` function pointer")
-                    }
-                    _ => {}
-                }
-
-                let sig = cx.erase_late_bound_regions(&bare_fn.sig);
-                match sig.output {
-                    ty::FnDiverging => {}
-                    ty::FnConverging(output) => {
-                        if !output.is_nil() {
-                            let r = self.check_type_for_ffi(cache, output);
-                            match r {
-                                FfiSafe => {}
-                                _ => { return r; }
-                            }
-                        }
-                    }
-                }
-                for arg in sig.inputs {
-                    let r = self.check_type_for_ffi(cache, arg);
-                    match r {
-                        FfiSafe => {}
-                        _ => { return r; }
-                    }
-                }
-                FfiSafe
-            }
-
-            ty::TyParam(..) | ty::TyInfer(..) | ty::TyError |
-            ty::TyClosure(..) | ty::TyProjection(..) |
-            ty::TyBareFn(Some(_), _) => {
-                panic!("Unexpected type in foreign function")
-            }
-        }
-    }
-
-    fn check_def(&mut self, sp: Span, id: ast::NodeId) {
-        let tty = ast_ty_to_normalized(self.cx.tcx, id);
-
-        match ImproperCTypesVisitor::check_type_for_ffi(self, &mut FnvHashSet(), tty) {
-            FfiResult::FfiSafe => {}
-            FfiResult::FfiUnsafe(s) => {
-                self.cx.span_lint(IMPROPER_CTYPES, sp, s);
-            }
-            FfiResult::FfiBadStruct(_, s) => {
-                // FIXME: This diagnostic is difficult to read, and doesn't
-                // point at the relevant field.
-                self.cx.span_lint(IMPROPER_CTYPES, sp,
-                    &format!("found non-foreign-function-safe member in \
-                              struct marked #[repr(C)]: {}", s));
-            }
-            FfiResult::FfiBadEnum(_, s) => {
-                // FIXME: This diagnostic is difficult to read, and doesn't
-                // point at the relevant variant.
-                self.cx.span_lint(IMPROPER_CTYPES, sp,
-                    &format!("found non-foreign-function-safe member in \
-                              enum: {}", s));
-            }
-        }
-    }
-}
-
-impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> {
-    fn visit_ty(&mut self, ty: &hir::Ty) {
-        match ty.node {
-            hir::TyPath(..) |
-            hir::TyBareFn(..) => self.check_def(ty.span, ty.id),
-            hir::TyVec(..) => {
-                self.cx.span_lint(IMPROPER_CTYPES, ty.span,
-                    "found Rust slice type in foreign module, consider \
-                     using a raw pointer instead");
-            }
-            hir::TyFixedLengthVec(ref ty, _) => self.visit_ty(ty),
-            hir::TyTup(..) => {
-                self.cx.span_lint(IMPROPER_CTYPES, ty.span,
-                    "found Rust tuple type in foreign module; \
-                     consider using a struct instead`")
-            }
-            _ => visit::walk_ty(self, ty)
-        }
-    }
-}
-
-#[derive(Copy, Clone)]
-pub struct ImproperCTypes;
-
-impl LintPass for ImproperCTypes {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(IMPROPER_CTYPES)
-    }
-
-    fn check_item(&mut self, cx: &Context, it: &hir::Item) {
-        fn check_ty(cx: &Context, ty: &hir::Ty) {
-            let mut vis = ImproperCTypesVisitor { cx: cx };
-            vis.visit_ty(ty);
-        }
-
-        fn check_foreign_fn(cx: &Context, decl: &hir::FnDecl) {
-            for input in &decl.inputs {
-                check_ty(cx, &*input.ty);
-            }
-            if let hir::Return(ref ret_ty) = decl.output {
-                let tty = ast_ty_to_normalized(cx.tcx, ret_ty.id);
-                if !tty.is_nil() {
-                    check_ty(cx, &ret_ty);
-                }
-            }
-        }
-
-        match it.node {
-            hir::ItemForeignMod(ref nmod)
-                if nmod.abi != abi::RustIntrinsic &&
-                   nmod.abi != abi::PlatformIntrinsic => {
-                for ni in &nmod.items {
-                    match ni.node {
-                        hir::ForeignItemFn(ref decl, _) => check_foreign_fn(cx, &**decl),
-                        hir::ForeignItemStatic(ref t, _) => check_ty(cx, &**t)
-                    }
-                }
-            }
-            _ => (),
-        }
-    }
-}
-
-declare_lint! {
-    BOX_POINTERS,
-    Allow,
-    "use of owned (Box type) heap memory"
-}
-
-#[derive(Copy, Clone)]
-pub struct BoxPointers;
-
-impl BoxPointers {
-    fn check_heap_type<'a, 'tcx>(&self, cx: &Context<'a, 'tcx>,
-                                 span: Span, ty: Ty<'tcx>) {
-        for leaf_ty in ty.walk() {
-            if let ty::TyBox(_) = leaf_ty.sty {
-                let m = format!("type uses owned (Box type) pointers: {}", ty);
-                cx.span_lint(BOX_POINTERS, span, &m);
-            }
-        }
-    }
-}
-
-impl LintPass for BoxPointers {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(BOX_POINTERS)
-    }
-
-    fn check_item(&mut self, cx: &Context, it: &hir::Item) {
-        match it.node {
-            hir::ItemFn(..) |
-            hir::ItemTy(..) |
-            hir::ItemEnum(..) |
-            hir::ItemStruct(..) =>
-                self.check_heap_type(cx, it.span,
-                                     cx.tcx.node_id_to_type(it.id)),
-            _ => ()
-        }
-
-        // If it's a struct, we also have to check the fields' types
-        match it.node {
-            hir::ItemStruct(ref struct_def, _) => {
-                for struct_field in &struct_def.fields {
-                    self.check_heap_type(cx, struct_field.span,
-                                         cx.tcx.node_id_to_type(struct_field.node.id));
-                }
-            }
-            _ => ()
-        }
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &hir::Expr) {
-        let ty = cx.tcx.node_id_to_type(e.id);
-        self.check_heap_type(cx, e.span, ty);
-    }
-}
-
-declare_lint! {
-    RAW_POINTER_DERIVE,
-    Warn,
-    "uses of #[derive] with raw pointers are rarely correct"
-}
-
-struct RawPtrDeriveVisitor<'a, 'tcx: 'a> {
-    cx: &'a Context<'a, 'tcx>
-}
-
-impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDeriveVisitor<'a, 'tcx> {
-    fn visit_ty(&mut self, ty: &hir::Ty) {
-        const MSG: &'static str = "use of `#[derive]` with a raw pointer";
-        if let hir::TyPtr(..) = ty.node {
-            self.cx.span_lint(RAW_POINTER_DERIVE, ty.span, MSG);
-        }
-        visit::walk_ty(self, ty);
-    }
-    // explicit override to a no-op to reduce code bloat
-    fn visit_expr(&mut self, _: &hir::Expr) {}
-    fn visit_block(&mut self, _: &hir::Block) {}
-}
-
-pub struct RawPointerDerive {
-    checked_raw_pointers: NodeSet,
-}
-
-impl RawPointerDerive {
-    pub fn new() -> RawPointerDerive {
-        RawPointerDerive {
-            checked_raw_pointers: NodeSet(),
-        }
-    }
-}
-
-impl LintPass for RawPointerDerive {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(RAW_POINTER_DERIVE)
-    }
-
-    fn check_item(&mut self, cx: &Context, item: &hir::Item) {
-        if !attr::contains_name(&item.attrs, "automatically_derived") {
-            return;
-        }
-        let did = match item.node {
-            hir::ItemImpl(_, _, _, ref t_ref_opt, _, _) => {
-                // Deriving the Copy trait does not cause a warning
-                if let &Some(ref trait_ref) = t_ref_opt {
-                    let def_id = cx.tcx.trait_ref_to_def_id(trait_ref);
-                    if Some(def_id) == cx.tcx.lang_items.copy_trait() {
-                        return;
-                    }
-                }
-
-                match cx.tcx.node_id_to_type(item.id).sty {
-                    ty::TyEnum(def, _) => def.did,
-                    ty::TyStruct(def, _) => def.did,
-                    _ => return,
-                }
-            }
-            _ => return,
-        };
-        if !did.is_local() {
-            return;
-        }
-        let item = match cx.tcx.map.find(did.node) {
-            Some(hir_map::NodeItem(item)) => item,
-            _ => return,
-        };
-        if !self.checked_raw_pointers.insert(item.id) {
-            return;
-        }
-        match item.node {
-            hir::ItemStruct(..) | hir::ItemEnum(..) => {
-                let mut visitor = RawPtrDeriveVisitor { cx: cx };
-                visit::walk_item(&mut visitor, &item);
-            }
-            _ => {}
-        }
-    }
-}
-
-declare_lint! {
-    UNUSED_ATTRIBUTES,
-    Warn,
-    "detects attributes that were not used by the compiler"
-}
-
-#[derive(Copy, Clone)]
-pub struct UnusedAttributes;
-
-impl LintPass for UnusedAttributes {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_ATTRIBUTES)
-    }
-
-    fn check_attribute(&mut self, cx: &Context, attr: &hir::Attribute) {
-        // Note that check_name() marks the attribute as used if it matches.
-        for &(ref name, ty, _) in KNOWN_ATTRIBUTES {
-            match ty {
-                AttributeType::Whitelisted if attr.check_name(name) => {
-                    break;
-                },
-                _ => ()
-            }
-        }
-
-        let plugin_attributes = cx.sess().plugin_attributes.borrow_mut();
-        for &(ref name, ty) in plugin_attributes.iter() {
-            if ty == AttributeType::Whitelisted && attr.check_name(&*name) {
-                break;
-            }
-        }
-
-        if !syntax_attr::is_used(&unlower_attribute(attr)) {
-            cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
-            // Is it a builtin attribute that must be used at the crate level?
-            let known_crate = KNOWN_ATTRIBUTES.iter().find(|&&(name, ty, _)| {
-                attr.name() == name &&
-                ty == AttributeType::CrateLevel
-            }).is_some();
-
-            // Has a plugin registered this attribute as one which must be used at
-            // the crate level?
-            let plugin_crate = plugin_attributes.iter()
-                                                .find(|&&(ref x, t)| {
-                                                        &*attr.name() == &*x &&
-                                                        AttributeType::CrateLevel == t
-                                                    }).is_some();
-            if  known_crate || plugin_crate {
-                let msg = match attr.node.style {
-                    hir::AttrOuter => "crate-level attribute should be an inner \
-                                       attribute: add an exclamation mark: #![foo]",
-                    hir::AttrInner => "crate-level attribute should be in the \
-                                       root module",
-                };
-                cx.span_lint(UNUSED_ATTRIBUTES, attr.span, msg);
-            }
-        }
-    }
-}
-
-declare_lint! {
-    pub PATH_STATEMENTS,
-    Warn,
-    "path statements with no effect"
-}
-
-#[derive(Copy, Clone)]
-pub struct PathStatements;
-
-impl LintPass for PathStatements {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(PATH_STATEMENTS)
-    }
-
-    fn check_stmt(&mut self, cx: &Context, s: &hir::Stmt) {
-        match s.node {
-            hir::StmtSemi(ref expr, _) => {
-                match expr.node {
-                    hir::ExprPath(..) => cx.span_lint(PATH_STATEMENTS, s.span,
-                                                      "path statement with no effect"),
-                    _ => ()
-                }
-            }
-            _ => ()
-        }
-    }
-}
-
-declare_lint! {
-    pub UNUSED_MUST_USE,
-    Warn,
-    "unused result of a type flagged as #[must_use]"
-}
-
-declare_lint! {
-    pub UNUSED_RESULTS,
-    Allow,
-    "unused result of an expression in a statement"
-}
-
-#[derive(Copy, Clone)]
-pub struct UnusedResults;
-
-impl LintPass for UnusedResults {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_MUST_USE, UNUSED_RESULTS)
-    }
-
-    fn check_stmt(&mut self, cx: &Context, s: &hir::Stmt) {
-        let expr = match s.node {
-            hir::StmtSemi(ref expr, _) => &**expr,
-            _ => return
-        };
-
-        if let hir::ExprRet(..) = expr.node {
-            return;
-        }
-
-        let t = cx.tcx.expr_ty(&expr);
-        let warned = match t.sty {
-            ty::TyTuple(ref tys) if tys.is_empty() => return,
-            ty::TyBool => return,
-            ty::TyStruct(def, _) |
-            ty::TyEnum(def, _) => {
-                if def.did.is_local() {
-                    if let hir_map::NodeItem(it) = cx.tcx.map.get(def.did.node) {
-                        check_must_use(cx, &it.attrs, s.span)
-                    } else {
-                        false
-                    }
-                } else {
-                    let attrs = csearch::get_item_attrs(&cx.sess().cstore, def.did);
-                    check_must_use(cx, &attrs[..], s.span)
-                }
-            }
-            _ => false,
-        };
-        if !warned {
-            cx.span_lint(UNUSED_RESULTS, s.span, "unused result");
-        }
-
-        fn check_must_use(cx: &Context, attrs: &[hir::Attribute], sp: Span) -> bool {
-            for attr in attrs {
-                if attr.check_name("must_use") {
-                    let mut msg = "unused result which must be used".to_string();
-                    // check for #[must_use="..."]
-                    match attr.value_str() {
-                        None => {}
-                        Some(s) => {
-                            msg.push_str(": ");
-                            msg.push_str(&s);
-                        }
-                    }
-                    cx.span_lint(UNUSED_MUST_USE, sp, &msg);
-                    return true;
-                }
-            }
-            false
-        }
-    }
-}
-
-declare_lint! {
-    pub NON_CAMEL_CASE_TYPES,
-    Warn,
-    "types, variants, traits and type parameters should have camel case names"
-}
-
-#[derive(Copy, Clone)]
-pub struct NonCamelCaseTypes;
-
-impl NonCamelCaseTypes {
-    fn check_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
-        fn is_camel_case(ident: ast::Ident) -> bool {
-            let ident = ident.name.as_str();
-            if ident.is_empty() {
-                return true;
-            }
-            let ident = ident.trim_matches('_');
-
-            // start with a non-lowercase letter rather than non-uppercase
-            // ones (some scripts don't have a concept of upper/lowercase)
-            !ident.is_empty() && !ident.char_at(0).is_lowercase() && !ident.contains('_')
-        }
-
-        fn to_camel_case(s: &str) -> String {
-            s.split('_').flat_map(|word| word.chars().enumerate().map(|(i, c)|
-                if i == 0 {
-                    c.to_uppercase().collect::<String>()
-                } else {
-                    c.to_lowercase().collect()
-                }
-            )).collect::<Vec<_>>().concat()
-        }
-
-        let s = ident.name.as_str();
-
-        if !is_camel_case(ident) {
-            let c = to_camel_case(&s);
-            let m = if c.is_empty() {
-                format!("{} `{}` should have a camel case name such as `CamelCase`", sort, s)
-            } else {
-                format!("{} `{}` should have a camel case name such as `{}`", sort, s, c)
-            };
-            cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m[..]);
-        }
-    }
-}
-
-impl LintPass for NonCamelCaseTypes {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_CAMEL_CASE_TYPES)
-    }
-
-    fn check_item(&mut self, cx: &Context, it: &hir::Item) {
-        let extern_repr_count = it.attrs.iter().filter(|attr| {
-            attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr).iter()
-                .any(|r| r == &attr::ReprExtern)
-        }).count();
-        let has_extern_repr = extern_repr_count > 0;
-
-        if has_extern_repr {
-            return;
-        }
-
-        match it.node {
-            hir::ItemTy(..) | hir::ItemStruct(..) => {
-                self.check_case(cx, "type", it.ident, it.span)
-            }
-            hir::ItemTrait(..) => {
-                self.check_case(cx, "trait", it.ident, it.span)
-            }
-            hir::ItemEnum(ref enum_definition, _) => {
-                if has_extern_repr {
-                    return;
-                }
-                self.check_case(cx, "type", it.ident, it.span);
-                for variant in &enum_definition.variants {
-                    self.check_case(cx, "variant", variant.node.name, variant.span);
-                }
-            }
-            _ => ()
-        }
-    }
-
-    fn check_generics(&mut self, cx: &Context, it: &hir::Generics) {
-        for gen in it.ty_params.iter() {
-            self.check_case(cx, "type parameter", gen.ident, gen.span);
-        }
-    }
-}
-
-#[derive(PartialEq)]
-enum MethodContext {
-    TraitDefaultImpl,
-    TraitImpl,
-    PlainImpl
-}
-
-fn method_context(cx: &Context, id: ast::NodeId, span: Span) -> MethodContext {
-    match cx.tcx.impl_or_trait_items.borrow().get(&DefId::local(id)) {
-        None => cx.sess().span_bug(span, "missing method descriptor?!"),
-        Some(item) => match item.container() {
-            ty::TraitContainer(..) => MethodContext::TraitDefaultImpl,
-            ty::ImplContainer(cid) => {
-                match cx.tcx.impl_trait_ref(cid) {
-                    Some(_) => MethodContext::TraitImpl,
-                    None => MethodContext::PlainImpl
-                }
-            }
-        }
-    }
-}
-
-declare_lint! {
-    pub NON_SNAKE_CASE,
-    Warn,
-    "methods, functions, lifetime parameters and modules should have snake case names"
-}
-
-#[derive(Copy, Clone)]
-pub struct NonSnakeCase;
-
-impl NonSnakeCase {
-    fn to_snake_case(mut str: &str) -> String {
-        let mut words = vec![];
-        // Preserve leading underscores
-        str = str.trim_left_matches(|c: char| {
-            if c == '_' {
-                words.push(String::new());
-                true
-            } else {
-                false
-            }
-        });
-        for s in str.split('_') {
-            let mut last_upper = false;
-            let mut buf = String::new();
-            if s.is_empty() {
-                continue;
-            }
-            for ch in s.chars() {
-                if !buf.is_empty() && buf != "'"
-                                   && ch.is_uppercase()
-                                   && !last_upper {
-                    words.push(buf);
-                    buf = String::new();
-                }
-                last_upper = ch.is_uppercase();
-                buf.extend(ch.to_lowercase());
-            }
-            words.push(buf);
-        }
-        words.join("_")
-    }
-
-    fn check_snake_case(&self, cx: &Context, sort: &str, name: &str, span: Option<Span>) {
-        fn is_snake_case(ident: &str) -> bool {
-            if ident.is_empty() {
-                return true;
-            }
-            let ident = ident.trim_left_matches('\'');
-            let ident = ident.trim_matches('_');
-
-            let mut allow_underscore = true;
-            ident.chars().all(|c| {
-                allow_underscore = match c {
-                    '_' if !allow_underscore => return false,
-                    '_' => false,
-                    // It would be more obvious to use `c.is_lowercase()`,
-                    // but some characters do not have a lowercase form
-                    c if !c.is_uppercase() => true,
-                    _ => return false,
-                };
-                true
-            })
-        }
-
-        if !is_snake_case(name) {
-            let sc = NonSnakeCase::to_snake_case(name);
-            let msg = if sc != name {
-                format!("{} `{}` should have a snake case name such as `{}`",
-                        sort, name, sc)
-            } else {
-                format!("{} `{}` should have a snake case name",
-                        sort, name)
-            };
-            match span {
-                Some(span) => cx.span_lint(NON_SNAKE_CASE, span, &msg),
-                None => cx.lint(NON_SNAKE_CASE, &msg),
-            }
-        }
-    }
-}
-
-impl LintPass for NonSnakeCase {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_SNAKE_CASE)
-    }
-
-    fn check_crate(&mut self, cx: &Context, cr: &hir::Crate) {
-        let attr_crate_name = cr.attrs.iter().find(|at| at.check_name("crate_name"))
-                                      .and_then(|at| at.value_str().map(|s| (at, s)));
-        if let Some(ref name) = cx.tcx.sess.opts.crate_name {
-            self.check_snake_case(cx, "crate", name, None);
-        } else if let Some((attr, ref name)) = attr_crate_name {
-            self.check_snake_case(cx, "crate", name, Some(attr.span));
-        }
-    }
-
-    fn check_fn(&mut self, cx: &Context,
-                fk: FnKind, _: &hir::FnDecl,
-                _: &hir::Block, span: Span, id: ast::NodeId) {
-        match fk {
-            FnKind::Method(ident, _, _) => match method_context(cx, id, span) {
-                MethodContext::PlainImpl => {
-                    self.check_snake_case(cx, "method", &ident.name.as_str(), Some(span))
-                },
-                MethodContext::TraitDefaultImpl => {
-                    self.check_snake_case(cx, "trait method", &ident.name.as_str(), Some(span))
-                },
-                _ => (),
-            },
-            FnKind::ItemFn(ident, _, _, _, _, _) => {
-                self.check_snake_case(cx, "function", &ident.name.as_str(), Some(span))
-            },
-            _ => (),
-        }
-    }
-
-    fn check_item(&mut self, cx: &Context, it: &hir::Item) {
-        if let hir::ItemMod(_) = it.node {
-            self.check_snake_case(cx, "module", &it.ident.name.as_str(), Some(it.span));
-        }
-    }
+use bad_style::{MethodLateContext, method_context};
 
-    fn check_trait_item(&mut self, cx: &Context, trait_item: &hir::TraitItem) {
-        if let hir::MethodTraitItem(_, None) = trait_item.node {
-            self.check_snake_case(cx, "trait method", &trait_item.ident.name.as_str(),
-                                  Some(trait_item.span));
-        }
-    }
+// hardwired lints from librustc
+pub use lint::builtin::*;
 
-    fn check_lifetime_def(&mut self, cx: &Context, t: &hir::LifetimeDef) {
-        self.check_snake_case(cx, "lifetime", &t.lifetime.name.as_str(),
-                              Some(t.lifetime.span));
-    }
+declare_lint! {
+    WHILE_TRUE,
+    Warn,
+    "suggest using `loop { }` instead of `while true { }`"
+}
 
-    fn check_pat(&mut self, cx: &Context, p: &hir::Pat) {
-        if let &hir::PatIdent(_, ref path1, _) = &p.node {
-            let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
-            if let Some(def::DefLocal(_)) = def {
-                self.check_snake_case(cx, "variable", &path1.node.name.as_str(), Some(p.span));
-            }
-        }
+#[derive(Copy, Clone)]
+pub struct WhileTrue;
+
+impl LintPass for WhileTrue {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(WHILE_TRUE)
     }
+}
 
-    fn check_struct_def(&mut self, cx: &Context, s: &hir::StructDef,
-                        _: ast::Ident, _: &hir::Generics, _: ast::NodeId) {
-        for sf in &s.fields {
-            if let hir::StructField_ { kind: hir::NamedField(ident, _), .. } = sf.node {
-                self.check_snake_case(cx, "structure field", &ident.name.as_str(),
-                                      Some(sf.span));
+impl LateLintPass for WhileTrue {
+    fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
+        if let hir::ExprWhile(ref cond, _, _) = e.node {
+            if let hir::ExprLit(ref lit) = cond.node {
+                if let ast::LitBool(true) = lit.node {
+                    cx.span_lint(WHILE_TRUE, e.span,
+                                 "denote infinite loops with loop { ... }");
+                }
             }
         }
     }
 }
 
 declare_lint! {
-    pub NON_UPPER_CASE_GLOBALS,
-    Warn,
-    "static constants should have uppercase identifiers"
+    BOX_POINTERS,
+    Allow,
+    "use of owned (Box type) heap memory"
 }
 
 #[derive(Copy, Clone)]
-pub struct NonUpperCaseGlobals;
-
-impl NonUpperCaseGlobals {
-    fn check_upper_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
-        let s = ident.name.as_str();
-
-        if s.chars().any(|c| c.is_lowercase()) {
-            let uc = NonSnakeCase::to_snake_case(&s).to_uppercase();
-            if uc != &s[..] {
-                cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
-                    &format!("{} `{}` should have an upper case name such as `{}`",
-                             sort, s, uc));
-            } else {
-                cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
-                    &format!("{} `{}` should have an upper case name",
-                             sort, s));
+pub struct BoxPointers;
+
+impl BoxPointers {
+    fn check_heap_type<'a, 'tcx>(&self, cx: &LateContext<'a, 'tcx>,
+                                 span: Span, ty: Ty<'tcx>) {
+        for leaf_ty in ty.walk() {
+            if let ty::TyBox(_) = leaf_ty.sty {
+                let m = format!("type uses owned (Box type) pointers: {}", ty);
+                cx.span_lint(BOX_POINTERS, span, &m);
             }
         }
     }
 }
 
-impl LintPass for NonUpperCaseGlobals {
+impl LintPass for BoxPointers {
     fn get_lints(&self) -> LintArray {
-        lint_array!(NON_UPPER_CASE_GLOBALS)
+        lint_array!(BOX_POINTERS)
     }
+}
 
-    fn check_item(&mut self, cx: &Context, it: &hir::Item) {
+impl LateLintPass for BoxPointers {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         match it.node {
-            // only check static constants
-            hir::ItemStatic(_, hir::MutImmutable, _) => {
-                NonUpperCaseGlobals::check_upper_case(cx, "static constant", it.ident, it.span);
-            }
-            hir::ItemConst(..) => {
-                NonUpperCaseGlobals::check_upper_case(cx, "constant", it.ident, it.span);
-            }
-            _ => {}
-        }
-    }
-
-    fn check_trait_item(&mut self, cx: &Context, ti: &hir::TraitItem) {
-        match ti.node {
-            hir::ConstTraitItem(..) => {
-                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
-                                                      ti.ident, ti.span);
-            }
-            _ => {}
+            hir::ItemFn(..) |
+            hir::ItemTy(..) |
+            hir::ItemEnum(..) |
+            hir::ItemStruct(..) =>
+                self.check_heap_type(cx, it.span,
+                                     cx.tcx.node_id_to_type(it.id)),
+            _ => ()
         }
-    }
 
-    fn check_impl_item(&mut self, cx: &Context, ii: &hir::ImplItem) {
-        match ii.node {
-            hir::ConstImplItem(..) => {
-                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
-                                                      ii.ident, ii.span);
+        // If it's a struct, we also have to check the fields' types
+        match it.node {
+            hir::ItemStruct(ref struct_def, _) => {
+                for struct_field in struct_def.fields() {
+                    self.check_heap_type(cx, struct_field.span,
+                                         cx.tcx.node_id_to_type(struct_field.node.id));
+                }
             }
-            _ => {}
+            _ => ()
         }
     }
 
-    fn check_pat(&mut self, cx: &Context, p: &hir::Pat) {
-        // Lint for constants that look like binding identifiers (#7526)
-        match (&p.node, cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def())) {
-            (&hir::PatIdent(_, ref path1, _), Some(def::DefConst(..))) => {
-                NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern",
-                                                      path1.node, p.span);
-            }
-            _ => {}
-        }
+    fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
+        let ty = cx.tcx.node_id_to_type(e.id);
+        self.check_heap_type(cx, e.span, ty);
     }
 }
 
 declare_lint! {
-    UNUSED_PARENS,
+    RAW_POINTER_DERIVE,
     Warn,
-    "`if`, `match`, `while` and `return` do not need parentheses"
+    "uses of #[derive] with raw pointers are rarely correct"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedParens;
-
-impl UnusedParens {
-    fn check_unused_parens_core(&self, cx: &Context, value: &hir::Expr, msg: &str,
-                                struct_lit_needs_parens: bool) {
-        if let hir::ExprParen(ref inner) = value.node {
-            let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&**inner);
-            if !necessary {
-                cx.span_lint(UNUSED_PARENS, value.span,
-                             &format!("unnecessary parentheses around {}", msg))
-            }
-        }
-
-        /// Expressions that syntactically contain an "exterior" struct
-        /// literal i.e. not surrounded by any parens or other
-        /// delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo
-        /// == X { y: 1 }` and `X { y: 1 } == foo` all do, but `(X {
-        /// y: 1 }) == foo` does not.
-        fn contains_exterior_struct_lit(value: &hir::Expr) -> bool {
-            match value.node {
-                hir::ExprStruct(..) => true,
-
-                hir::ExprAssign(ref lhs, ref rhs) |
-                hir::ExprAssignOp(_, ref lhs, ref rhs) |
-                hir::ExprBinary(_, ref lhs, ref rhs) => {
-                    // X { y: 1 } + X { y: 2 }
-                    contains_exterior_struct_lit(&**lhs) ||
-                        contains_exterior_struct_lit(&**rhs)
-                }
-                hir::ExprUnary(_, ref x) |
-                hir::ExprCast(ref x, _) |
-                hir::ExprField(ref x, _) |
-                hir::ExprTupField(ref x, _) |
-                hir::ExprIndex(ref x, _) => {
-                    // &X { y: 1 }, X { y: 1 }.y
-                    contains_exterior_struct_lit(&**x)
-                }
-
-                hir::ExprMethodCall(_, _, ref exprs) => {
-                    // X { y: 1 }.bar(...)
-                    contains_exterior_struct_lit(&*exprs[0])
-                }
+struct RawPtrDeriveVisitor<'a, 'tcx: 'a> {
+    cx: &'a LateContext<'a, 'tcx>
+}
 
-                _ => false
-            }
+impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDeriveVisitor<'a, 'tcx> {
+    fn visit_ty(&mut self, ty: &hir::Ty) {
+        const MSG: &'static str = "use of `#[derive]` with a raw pointer";
+        if let hir::TyPtr(..) = ty.node {
+            self.cx.span_lint(RAW_POINTER_DERIVE, ty.span, MSG);
         }
+        visit::walk_ty(self, ty);
     }
+    // explicit override to a no-op to reduce code bloat
+    fn visit_expr(&mut self, _: &hir::Expr) {}
+    fn visit_block(&mut self, _: &hir::Block) {}
 }
 
-impl LintPass for UnusedParens {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_PARENS)
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &hir::Expr) {
-        let (value, msg, struct_lit_needs_parens) = match e.node {
-            hir::ExprIf(ref cond, _, _) => (cond, "`if` condition", true),
-            hir::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true),
-            hir::ExprMatch(ref head, _, source) => match source {
-                hir::MatchSource::Normal => (head, "`match` head expression", true),
-                hir::MatchSource::IfLetDesugar { .. } => (head, "`if let` head expression", true),
-                hir::MatchSource::WhileLetDesugar => (head, "`while let` head expression", true),
-                hir::MatchSource::ForLoopDesugar => (head, "`for` head expression", true),
-            },
-            hir::ExprRet(Some(ref value)) => (value, "`return` value", false),
-            hir::ExprAssign(_, ref value) => (value, "assigned value", false),
-            hir::ExprAssignOp(_, _, ref value) => (value, "assigned value", false),
-            _ => return
-        };
-        self.check_unused_parens_core(cx, &**value, msg, struct_lit_needs_parens);
-    }
-
-    fn check_stmt(&mut self, cx: &Context, s: &hir::Stmt) {
-        let (value, msg) = match s.node {
-            hir::StmtDecl(ref decl, _) => match decl.node {
-                hir::DeclLocal(ref local) => match local.init {
-                    Some(ref value) => (value, "assigned value"),
-                    None => return
-                },
-                _ => return
-            },
-            _ => return
-        };
-        self.check_unused_parens_core(cx, &**value, msg, false);
-    }
+pub struct RawPointerDerive {
+    checked_raw_pointers: NodeSet,
 }
 
-declare_lint! {
-    UNUSED_IMPORT_BRACES,
-    Allow,
-    "unnecessary braces around an imported item"
+impl RawPointerDerive {
+    pub fn new() -> RawPointerDerive {
+        RawPointerDerive {
+            checked_raw_pointers: NodeSet(),
+        }
+    }
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedImportBraces;
-
-impl LintPass for UnusedImportBraces {
+impl LintPass for RawPointerDerive {
     fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_IMPORT_BRACES)
+        lint_array!(RAW_POINTER_DERIVE)
     }
+}
 
-    fn check_item(&mut self, cx: &Context, item: &hir::Item) {
-        if let hir::ItemUse(ref view_path) = item.node {
-            if let hir::ViewPathList(_, ref items) = view_path.node {
-                if items.len() == 1 {
-                    if let hir::PathListIdent {ref name, ..} = items[0].node {
-                        let m = format!("braces around {} is unnecessary",
-                                        name);
-                        cx.span_lint(UNUSED_IMPORT_BRACES, item.span,
-                                     &m[..]);
+impl LateLintPass for RawPointerDerive {
+    fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
+        if !attr::contains_name(&item.attrs, "automatically_derived") {
+            return;
+        }
+        let did = match item.node {
+            hir::ItemImpl(_, _, _, ref t_ref_opt, _, _) => {
+                // Deriving the Copy trait does not cause a warning
+                if let &Some(ref trait_ref) = t_ref_opt {
+                    let def_id = cx.tcx.trait_ref_to_def_id(trait_ref);
+                    if Some(def_id) == cx.tcx.lang_items.copy_trait() {
+                        return;
                     }
                 }
+
+                match cx.tcx.node_id_to_type(item.id).sty {
+                    ty::TyEnum(def, _) => def.did,
+                    ty::TyStruct(def, _) => def.did,
+                    _ => return,
+                }
+            }
+            _ => return,
+        };
+        let node_id = if let Some(node_id) = cx.tcx.map.as_local_node_id(did) {
+            node_id
+        } else {
+            return;
+        };
+        let item = match cx.tcx.map.find(node_id) {
+            Some(hir_map::NodeItem(item)) => item,
+            _ => return,
+        };
+        if !self.checked_raw_pointers.insert(item.id) {
+            return;
+        }
+        match item.node {
+            hir::ItemStruct(..) | hir::ItemEnum(..) => {
+                let mut visitor = RawPtrDeriveVisitor { cx: cx };
+                visit::walk_item(&mut visitor, &item);
             }
+            _ => {}
         }
     }
 }
@@ -1513,8 +237,10 @@ impl LintPass for NonShorthandFieldPatterns {
     fn get_lints(&self) -> LintArray {
         lint_array!(NON_SHORTHAND_FIELD_PATTERNS)
     }
+}
 
-    fn check_pat(&mut self, cx: &Context, pat: &hir::Pat) {
+impl LateLintPass for NonShorthandFieldPatterns {
+    fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
         let def_map = cx.tcx.def_map.borrow();
         if let hir::PatStruct(_, ref v, _) = pat.node {
             let field_pats = v.iter().filter(|fieldpat| {
@@ -1522,11 +248,15 @@ impl LintPass for NonShorthandFieldPatterns {
                     return false;
                 }
                 let def = def_map.get(&fieldpat.node.pat.id).map(|d| d.full_def());
-                def == Some(def::DefLocal(fieldpat.node.pat.id))
+                if let Some(def_id) = cx.tcx.map.opt_local_def_id(fieldpat.node.pat.id) {
+                    def == Some(def::DefLocal(def_id, fieldpat.node.pat.id))
+                } else {
+                    false
+                }
             });
             for fieldpat in field_pats {
                 if let hir::PatIdent(_, ident, None) = fieldpat.node.pat.node {
-                    if ident.node.name == fieldpat.node.ident.name {
+                    if ident.node.name == fieldpat.node.name {
                         // FIXME: should this comparison really be done on the name?
                         // doing it on the ident will fail during compilation of libcore
                         cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span,
@@ -1539,31 +269,6 @@ impl LintPass for NonShorthandFieldPatterns {
     }
 }
 
-declare_lint! {
-    pub UNUSED_UNSAFE,
-    Warn,
-    "unnecessary use of an `unsafe` block"
-}
-
-#[derive(Copy, Clone)]
-pub struct UnusedUnsafe;
-
-impl LintPass for UnusedUnsafe {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_UNSAFE)
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &hir::Expr) {
-        if let hir::ExprBlock(ref blk) = e.node {
-            // Don't warn about generated blocks, that'll just pollute the output.
-            if blk.rules == hir::UnsafeBlock(hir::UserProvided) &&
-                !cx.tcx.used_unsafe.borrow().contains(&blk.id) {
-                    cx.span_lint(UNUSED_UNSAFE, blk.span, "unnecessary `unsafe` block");
-            }
-        }
-    }
-}
-
 declare_lint! {
     UNSAFE_CODE,
     Allow,
@@ -1577,8 +282,10 @@ impl LintPass for UnsafeCode {
     fn get_lints(&self) -> LintArray {
         lint_array!(UNSAFE_CODE)
     }
+}
 
-    fn check_expr(&mut self, cx: &Context, e: &hir::Expr) {
+impl LateLintPass for UnsafeCode {
+    fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
         if let hir::ExprBlock(ref blk) = e.node {
             // Don't warn about generated blocks, that'll just pollute the output.
             if blk.rules == hir::UnsafeBlock(hir::UserProvided) {
@@ -1587,7 +294,7 @@ impl LintPass for UnsafeCode {
         }
     }
 
-    fn check_item(&mut self, cx: &Context, it: &hir::Item) {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         match it.node {
             hir::ItemTrait(hir::Unsafety::Unsafe, _, _, _) =>
                 cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` trait"),
@@ -1599,7 +306,7 @@ impl LintPass for UnsafeCode {
         }
     }
 
-    fn check_fn(&mut self, cx: &Context, fk: FnKind, _: &hir::FnDecl,
+    fn check_fn(&mut self, cx: &LateContext, fk: FnKind, _: &hir::FnDecl,
                 _: &hir::Block, span: Span, _: ast::NodeId) {
         match fk {
             FnKind::ItemFn(_, _, hir::Unsafety::Unsafe, _, _, _) =>
@@ -1615,7 +322,7 @@ impl LintPass for UnsafeCode {
         }
     }
 
-    fn check_trait_item(&mut self, cx: &Context, trait_item: &hir::TraitItem) {
+    fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) {
         if let hir::MethodTraitItem(ref sig, None) = trait_item.node {
             if sig.unsafety == hir::Unsafety::Unsafe {
                 cx.span_lint(UNSAFE_CODE, trait_item.span,
@@ -1625,115 +332,6 @@ impl LintPass for UnsafeCode {
     }
 }
 
-declare_lint! {
-    pub UNUSED_MUT,
-    Warn,
-    "detect mut variables which don't need to be mutable"
-}
-
-#[derive(Copy, Clone)]
-pub struct UnusedMut;
-
-impl UnusedMut {
-    fn check_unused_mut_pat(&self, cx: &Context, pats: &[P<hir::Pat>]) {
-        // collect all mutable pattern and group their NodeIDs by their Identifier to
-        // avoid false warnings in match arms with multiple patterns
-
-        let mut mutables = FnvHashMap();
-        for p in pats {
-            pat_util::pat_bindings(&cx.tcx.def_map, p, |mode, id, _, path1| {
-                let ident = path1.node;
-                if let hir::BindByValue(hir::MutMutable) = mode {
-                    if !ident.name.as_str().starts_with("_") {
-                        match mutables.entry(ident.name.usize()) {
-                            Vacant(entry) => { entry.insert(vec![id]); },
-                            Occupied(mut entry) => { entry.get_mut().push(id); },
-                        }
-                    }
-                }
-            });
-        }
-
-        let used_mutables = cx.tcx.used_mut_nodes.borrow();
-        for (_, v) in &mutables {
-            if !v.iter().any(|e| used_mutables.contains(e)) {
-                cx.span_lint(UNUSED_MUT, cx.tcx.map.span(v[0]),
-                             "variable does not need to be mutable");
-            }
-        }
-    }
-}
-
-impl LintPass for UnusedMut {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_MUT)
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &hir::Expr) {
-        if let hir::ExprMatch(_, ref arms, _) = e.node {
-            for a in arms {
-                self.check_unused_mut_pat(cx, &a.pats)
-            }
-        }
-    }
-
-    fn check_stmt(&mut self, cx: &Context, s: &hir::Stmt) {
-        if let hir::StmtDecl(ref d, _) = s.node {
-            if let hir::DeclLocal(ref l) = d.node {
-                self.check_unused_mut_pat(cx, slice::ref_slice(&l.pat));
-            }
-        }
-    }
-
-    fn check_fn(&mut self, cx: &Context,
-                _: FnKind, decl: &hir::FnDecl,
-                _: &hir::Block, _: Span, _: ast::NodeId) {
-        for a in &decl.inputs {
-            self.check_unused_mut_pat(cx, slice::ref_slice(&a.pat));
-        }
-    }
-}
-
-declare_lint! {
-    UNUSED_ALLOCATION,
-    Warn,
-    "detects unnecessary allocations that can be eliminated"
-}
-
-#[derive(Copy, Clone)]
-pub struct UnusedAllocation;
-
-impl LintPass for UnusedAllocation {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_ALLOCATION)
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &hir::Expr) {
-        match e.node {
-            hir::ExprUnary(hir::UnUniq, _) => (),
-            _ => return
-        }
-
-        if let Some(adjustment) = cx.tcx.tables.borrow().adjustments.get(&e.id) {
-            if let adjustment::AdjustDerefRef(adjustment::AutoDerefRef {
-                ref autoref, ..
-            }) = *adjustment {
-                match autoref {
-                    &Some(adjustment::AutoPtr(_, hir::MutImmutable)) => {
-                        cx.span_lint(UNUSED_ALLOCATION, e.span,
-                                     "unnecessary allocation, use & instead");
-                    }
-                    &Some(adjustment::AutoPtr(_, hir::MutMutable)) => {
-                        cx.span_lint(UNUSED_ALLOCATION, e.span,
-                                     "unnecessary allocation, use &mut instead");
-                    }
-                    _ => ()
-                }
-            }
-        }
-    }
-}
-
 declare_lint! {
     MISSING_DOCS,
     Allow,
@@ -1770,9 +368,9 @@ impl MissingDoc {
     }
 
     fn check_missing_docs_attrs(&self,
-                               cx: &Context,
+                               cx: &LateContext,
                                id: Option<ast::NodeId>,
-                               attrs: &[hir::Attribute],
+                               attrs: &[ast::Attribute],
                                sp: Span,
                                desc: &'static str) {
         // If we're building a test harness, then warning about
@@ -1797,7 +395,7 @@ impl MissingDoc {
 
         let has_doc = attrs.iter().any(|a| {
             match a.node.value.node {
-                hir::MetaNameValue(ref name, _) if *name == "doc" => true,
+                ast::MetaNameValue(ref name, _) if *name == "doc" => true,
                 _ => false
             }
         });
@@ -1812,8 +410,10 @@ impl LintPass for MissingDoc {
     fn get_lints(&self) -> LintArray {
         lint_array!(MISSING_DOCS)
     }
+}
 
-    fn enter_lint_attrs(&mut self, _: &Context, attrs: &[hir::Attribute]) {
+impl LateLintPass for MissingDoc {
+    fn enter_lint_attrs(&mut self, _: &LateContext, attrs: &[ast::Attribute]) {
         let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| {
             attr.check_name("doc") && match attr.meta_item_list() {
                 None => false,
@@ -1823,26 +423,26 @@ impl LintPass for MissingDoc {
         self.doc_hidden_stack.push(doc_hidden);
     }
 
-    fn exit_lint_attrs(&mut self, _: &Context, _: &[hir::Attribute]) {
+    fn exit_lint_attrs(&mut self, _: &LateContext, _: &[ast::Attribute]) {
         self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
     }
 
-    fn check_struct_def(&mut self, _: &Context, _: &hir::StructDef,
-                        _: ast::Ident, _: &hir::Generics, id: ast::NodeId) {
-        self.struct_def_stack.push(id);
+    fn check_struct_def(&mut self, _: &LateContext, _: &hir::VariantData,
+                        _: ast::Name, _: &hir::Generics, item_id: ast::NodeId) {
+        self.struct_def_stack.push(item_id);
     }
 
-    fn check_struct_def_post(&mut self, _: &Context, _: &hir::StructDef,
-                             _: ast::Ident, _: &hir::Generics, id: ast::NodeId) {
+    fn check_struct_def_post(&mut self, _: &LateContext, _: &hir::VariantData,
+                             _: ast::Name, _: &hir::Generics, item_id: ast::NodeId) {
         let popped = self.struct_def_stack.pop().expect("empty struct_def_stack");
-        assert!(popped == id);
+        assert!(popped == item_id);
     }
 
-    fn check_crate(&mut self, cx: &Context, krate: &hir::Crate) {
+    fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) {
         self.check_missing_docs_attrs(cx, None, &krate.attrs, krate.span, "crate");
     }
 
-    fn check_item(&mut self, cx: &Context, it: &hir::Item) {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         let desc = match it.node {
             hir::ItemFn(..) => "a function",
             hir::ItemMod(..) => "a module",
@@ -1864,13 +464,15 @@ impl LintPass for MissingDoc {
                 // If the trait is private, add the impl items to private_traits so they don't get
                 // reported for missing docs.
                 let real_trait = cx.tcx.trait_ref_to_def_id(trait_ref);
-                match cx.tcx.map.find(real_trait.node) {
-                    Some(hir_map::NodeItem(item)) => if item.vis == hir::Visibility::Inherited {
-                        for itm in impl_items {
-                            self.private_traits.insert(itm.id);
-                        }
-                    },
-                    _ => { }
+                if let Some(node_id) = cx.tcx.map.as_local_node_id(real_trait) {
+                    match cx.tcx.map.find(node_id) {
+                        Some(hir_map::NodeItem(item)) => if item.vis == hir::Visibility::Inherited {
+                            for itm in impl_items {
+                                self.private_traits.insert(itm.id);
+                            }
+                        },
+                        _ => { }
+                    }
                 }
                 return
             },
@@ -1882,7 +484,7 @@ impl LintPass for MissingDoc {
         self.check_missing_docs_attrs(cx, Some(it.id), &it.attrs, it.span, desc);
     }
 
-    fn check_trait_item(&mut self, cx: &Context, trait_item: &hir::TraitItem) {
+    fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) {
         if self.private_traits.contains(&trait_item.id) { return }
 
         let desc = match trait_item.node {
@@ -1896,9 +498,9 @@ impl LintPass for MissingDoc {
                                       trait_item.span, desc);
     }
 
-    fn check_impl_item(&mut self, cx: &Context, impl_item: &hir::ImplItem) {
+    fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) {
         // If the method is an impl for a trait, don't doc.
-        if method_context(cx, impl_item.id, impl_item.span) == MethodContext::TraitImpl {
+        if method_context(cx, impl_item.id, impl_item.span) == MethodLateContext::TraitImpl {
             return;
         }
 
@@ -1912,7 +514,7 @@ impl LintPass for MissingDoc {
                                       impl_item.span, desc);
     }
 
-    fn check_struct_field(&mut self, cx: &Context, sf: &hir::StructField) {
+    fn check_struct_field(&mut self, cx: &LateContext, sf: &hir::StructField) {
         if let hir::NamedField(_, vis) = sf.node.kind {
             if vis == hir::Public || self.in_variant {
                 let cur_struct_def = *self.struct_def_stack.last()
@@ -1924,13 +526,14 @@ impl LintPass for MissingDoc {
         }
     }
 
-    fn check_variant(&mut self, cx: &Context, v: &hir::Variant, _: &hir::Generics) {
-        self.check_missing_docs_attrs(cx, Some(v.node.id), &v.node.attrs, v.span, "a variant");
+    fn check_variant(&mut self, cx: &LateContext, v: &hir::Variant, _: &hir::Generics) {
+        self.check_missing_docs_attrs(cx, Some(v.node.data.id()),
+                                      &v.node.attrs, v.span, "a variant");
         assert!(!self.in_variant);
         self.in_variant = true;
     }
 
-    fn check_variant_post(&mut self, _: &Context, _: &hir::Variant, _: &hir::Generics) {
+    fn check_variant_post(&mut self, _: &LateContext, _: &hir::Variant, _: &hir::Generics) {
         assert!(self.in_variant);
         self.in_variant = false;
     }
@@ -1949,8 +552,10 @@ impl LintPass for MissingCopyImplementations {
     fn get_lints(&self) -> LintArray {
         lint_array!(MISSING_COPY_IMPLEMENTATIONS)
     }
+}
 
-    fn check_item(&mut self, cx: &Context, item: &hir::Item) {
+impl LateLintPass for MissingCopyImplementations {
+    fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
         if !cx.exported_items.contains(&item.id) {
             return;
         }
@@ -1959,7 +564,7 @@ impl LintPass for MissingCopyImplementations {
                 if ast_generics.is_parameterized() {
                     return;
                 }
-                let def = cx.tcx.lookup_adt_def(DefId::local(item.id));
+                let def = cx.tcx.lookup_adt_def(cx.tcx.map.local_def_id(item.id));
                 (def, cx.tcx.mk_struct(def,
                                        cx.tcx.mk_substs(Substs::empty())))
             }
@@ -1967,7 +572,7 @@ impl LintPass for MissingCopyImplementations {
                 if ast_generics.is_parameterized() {
                     return;
                 }
-                let def = cx.tcx.lookup_adt_def(DefId::local(item.id));
+                let def = cx.tcx.lookup_adt_def(cx.tcx.map.local_def_id(item.id));
                 (def, cx.tcx.mk_enum(def,
                                      cx.tcx.mk_substs(Substs::empty())))
             }
@@ -2011,8 +616,10 @@ impl LintPass for MissingDebugImplementations {
     fn get_lints(&self) -> LintArray {
         lint_array!(MISSING_DEBUG_IMPLEMENTATIONS)
     }
+}
 
-    fn check_item(&mut self, cx: &Context, item: &hir::Item) {
+impl LateLintPass for MissingDebugImplementations {
+    fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
         if !cx.exported_items.contains(&item.id) {
             return;
         }
@@ -2031,9 +638,11 @@ impl LintPass for MissingDebugImplementations {
             let debug_def = cx.tcx.lookup_trait_def(debug);
             let mut impls = NodeSet();
             debug_def.for_each_impl(cx.tcx, |d| {
-                if d.is_local() {
-                    if let Some(ty_def) = cx.tcx.node_id_to_type(d.node).ty_to_def_id() {
-                        impls.insert(ty_def.node);
+                if let Some(n) = cx.tcx.map.as_local_node_id(d) {
+                    if let Some(ty_def) = cx.tcx.node_id_to_type(n).ty_to_def_id() {
+                        if let Some(node_id) = cx.tcx.map.as_local_node_id(ty_def) {
+                            impls.insert(node_id);
+                        }
                     }
                 }
             });
@@ -2062,22 +671,22 @@ declare_lint! {
 pub struct Stability;
 
 impl Stability {
-    fn lint(&self, cx: &Context, _id: DefId,
+    fn lint(&self, cx: &LateContext, _id: DefId,
             span: Span, stability: &Option<&attr::Stability>) {
         // Deprecated attributes apply in-crate and cross-crate.
         let (lint, label) = match *stability {
-            Some(&attr::Stability { deprecated_since: Some(_), .. }) =>
+            Some(&attr::Stability { depr: Some(_), .. }) =>
                 (DEPRECATED, "deprecated"),
             _ => return
         };
 
         output(cx, span, stability, lint, label);
 
-        fn output(cx: &Context, span: Span, stability: &Option<&attr::Stability>,
+        fn output(cx: &LateContext, span: Span, stability: &Option<&attr::Stability>,
                   lint: &'static Lint, label: &'static str) {
             let msg = match *stability {
-                Some(&attr::Stability { reason: Some(ref s), .. }) => {
-                    format!("use of {} item: {}", label, *s)
+                Some(&attr::Stability {depr: Some(attr::Deprecation {ref reason, ..}), ..}) => {
+                    format!("use of {} item: {}", label, reason)
                 }
                 _ => format!("use of {} item", label)
             };
@@ -2087,51 +696,41 @@ impl Stability {
     }
 }
 
-fn hir_to_ast_stability(stab: &attr::Stability) -> attr::Stability {
-    attr::Stability {
-        level: match stab.level {
-            attr::Unstable => attr::Unstable,
-            attr::Stable => attr::Stable,
-        },
-        feature: stab.feature.clone(),
-        since: stab.since.clone(),
-        deprecated_since: stab.deprecated_since.clone(),
-        reason: stab.reason.clone(),
-        issue: stab.issue,
-    }
-}
-
 impl LintPass for Stability {
     fn get_lints(&self) -> LintArray {
         lint_array!(DEPRECATED)
     }
+}
 
-    fn check_item(&mut self, cx: &Context, item: &hir::Item) {
+impl LateLintPass for Stability {
+    fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
         stability::check_item(cx.tcx, item, false,
                               &mut |id, sp, stab|
-                                self.lint(cx, id, sp,
-                                          &stab.map(|s| hir_to_ast_stability(s)).as_ref()));
+                                self.lint(cx, id, sp, &stab));
     }
 
-    fn check_expr(&mut self, cx: &Context, e: &hir::Expr) {
+    fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
         stability::check_expr(cx.tcx, e,
                               &mut |id, sp, stab|
-                                self.lint(cx, id, sp,
-                                          &stab.map(|s| hir_to_ast_stability(s)).as_ref()));
+                                self.lint(cx, id, sp, &stab));
     }
 
-    fn check_path(&mut self, cx: &Context, path: &hir::Path, id: ast::NodeId) {
+    fn check_path(&mut self, cx: &LateContext, path: &hir::Path, id: ast::NodeId) {
         stability::check_path(cx.tcx, path, id,
                               &mut |id, sp, stab|
-                                self.lint(cx, id, sp,
-                                          &stab.map(|s| hir_to_ast_stability(s)).as_ref()));
+                                self.lint(cx, id, sp, &stab));
+    }
+
+    fn check_path_list_item(&mut self, cx: &LateContext, item: &hir::PathListItem) {
+        stability::check_path_list_item(cx.tcx, item,
+                                         &mut |id, sp, stab|
+                                           self.lint(cx, id, sp, &stab));
     }
 
-    fn check_pat(&mut self, cx: &Context, pat: &hir::Pat) {
+    fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
         stability::check_pat(cx.tcx, pat,
                              &mut |id, sp, stab|
-                                self.lint(cx, id, sp,
-                                          &stab.map(|s| hir_to_ast_stability(s)).as_ref()));
+                                self.lint(cx, id, sp, &stab));
     }
 }
 
@@ -2149,16 +748,15 @@ impl LintPass for UnconditionalRecursion {
     fn get_lints(&self) -> LintArray {
         lint_array![UNCONDITIONAL_RECURSION]
     }
+}
 
-    fn check_fn(&mut self, cx: &Context, fn_kind: FnKind, _: &hir::FnDecl,
+impl LateLintPass for UnconditionalRecursion {
+    fn check_fn(&mut self, cx: &LateContext, fn_kind: FnKind, _: &hir::FnDecl,
                 blk: &hir::Block, sp: Span, id: ast::NodeId) {
-        type F = for<'tcx> fn(&ty::ctxt<'tcx>,
-                              ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool;
-
         let method = match fn_kind {
             FnKind::ItemFn(..) => None,
             FnKind::Method(..) => {
-                cx.tcx.impl_or_trait_item(DefId::local(id)).as_opt_method()
+                cx.tcx.impl_or_trait_item(cx.tcx.map.local_def_id(id)).as_opt_method()
             }
             // closures can't recur, so they don't matter.
             FnKind::Closure => return
@@ -2271,8 +869,11 @@ impl LintPass for UnconditionalRecursion {
                                   id: ast::NodeId) -> bool {
             match tcx.map.get(id) {
                 hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => {
-                    tcx.def_map.borrow().get(&callee.id)
-                        .map_or(false, |def| def.def_id() == DefId::local(fn_id))
+                    tcx.def_map
+                       .borrow()
+                       .get(&callee.id)
+                       .map_or(false,
+                               |def| def.def_id() == tcx.map.local_def_id(fn_id))
                 }
                 _ => false
             }
@@ -2282,20 +883,22 @@ impl LintPass for UnconditionalRecursion {
         fn expr_refers_to_this_method(tcx: &ty::ctxt,
                                       method: &ty::Method,
                                       id: ast::NodeId) -> bool {
-            let tables = tcx.tables.borrow();
-
             // Check for method calls and overloaded operators.
-            if let Some(m) = tables.method_map.get(&ty::MethodCall::expr(id)) {
+            let opt_m = tcx.tables.borrow().method_map.get(&ty::MethodCall::expr(id)).cloned();
+            if let Some(m) = opt_m {
                 if method_call_refers_to_method(tcx, method, m.def_id, m.substs, id) {
                     return true;
                 }
             }
 
             // Check for overloaded autoderef method calls.
-            if let Some(&adjustment::AdjustDerefRef(ref adj)) = tables.adjustments.get(&id) {
+            let opt_adj = tcx.tables.borrow().adjustments.get(&id).cloned();
+            if let Some(adjustment::AdjustDerefRef(adj)) = opt_adj {
                 for i in 0..adj.autoderefs {
                     let method_call = ty::MethodCall::autoderef(id, i as u32);
-                    if let Some(m) = tables.method_map.get(&method_call) {
+                    if let Some(m) = tcx.tables.borrow().method_map
+                                                        .get(&method_call)
+                                                        .cloned() {
                         if method_call_refers_to_method(tcx, method, m.def_id, m.substs, id) {
                             return true;
                         }
@@ -2308,9 +911,13 @@ impl LintPass for UnconditionalRecursion {
                 hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => {
                     match tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def()) {
                         Some(def::DefMethod(def_id)) => {
-                            let no_substs = &ty::ItemSubsts::empty();
-                            let ts = tables.item_substs.get(&callee.id).unwrap_or(no_substs);
-                            method_call_refers_to_method(tcx, method, def_id, &ts.substs, id)
+                            let item_substs =
+                                tcx.tables.borrow().item_substs
+                                                   .get(&callee.id)
+                                                   .cloned()
+                                                   .unwrap_or_else(|| ty::ItemSubsts::empty());
+                            method_call_refers_to_method(
+                                tcx, method, def_id, &item_substs.substs, id)
                         }
                         _ => false
                     }
@@ -2347,7 +954,12 @@ impl LintPass for UnconditionalRecursion {
                         traits::Obligation::new(traits::ObligationCause::misc(span, expr_id),
                                                 trait_ref.to_poly_trait_predicate());
 
-                    let param_env = ty::ParameterEnvironment::for_item(tcx, method.def_id.node);
+                    // unwrap() is ok here b/c `method` is the method
+                    // defined in this crate whose body we are
+                    // checking, so it's always local
+                    let node_id = tcx.map.as_local_node_id(method.def_id).unwrap();
+
+                    let param_env = ty::ParameterEnvironment::for_item(tcx, node_id);
                     let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(param_env), false);
                     let mut selcx = traits::SelectionContext::new(&infcx);
                     match selcx.select(&obligation) {
@@ -2396,8 +1008,10 @@ impl LintPass for PluginAsLibrary {
     fn get_lints(&self) -> LintArray {
         lint_array![PLUGIN_AS_LIBRARY]
     }
+}
 
-    fn check_item(&mut self, cx: &Context, it: &hir::Item) {
+impl LateLintPass for PluginAsLibrary {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         if cx.sess().plugin_registrar_fn.get().is_some() {
             // We're compiling a plugin; it's fine to link other plugins.
             return;
@@ -2452,14 +1066,16 @@ impl LintPass for InvalidNoMangleItems {
                     PRIVATE_NO_MANGLE_STATICS,
                     NO_MANGLE_CONST_ITEMS)
     }
+}
 
-    fn check_item(&mut self, cx: &Context, it: &hir::Item) {
+impl LateLintPass for InvalidNoMangleItems {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         match it.node {
             hir::ItemFn(..) => {
                 if attr::contains_name(&it.attrs, "no_mangle") &&
                        !cx.exported_items.contains(&it.id) {
                     let msg = format!("function {} is marked #[no_mangle], but not exported",
-                                      it.ident);
+                                      it.name);
                     cx.span_lint(PRIVATE_NO_MANGLE_FNS, it.span, &msg);
                 }
             },
@@ -2467,7 +1083,7 @@ impl LintPass for InvalidNoMangleItems {
                 if attr::contains_name(&it.attrs, "no_mangle") &&
                        !cx.exported_items.contains(&it.id) {
                     let msg = format!("static {} is marked #[no_mangle], but not exported",
-                                      it.ident);
+                                      it.name);
                     cx.span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, &msg);
                 }
             },
@@ -2498,8 +1114,10 @@ impl LintPass for MutableTransmutes {
     fn get_lints(&self) -> LintArray {
         lint_array!(MUTABLE_TRANSMUTES)
     }
+}
 
-    fn check_expr(&mut self, cx: &Context, expr: &hir::Expr) {
+impl LateLintPass for MutableTransmutes {
+    fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
         use syntax::abi::RustIntrinsic;
 
         let msg = "mutating transmuted &mut T from &T may cause undefined behavior,\
@@ -2514,7 +1132,7 @@ impl LintPass for MutableTransmutes {
             _ => ()
         }
 
-        fn get_transmute_from_to<'a, 'tcx>(cx: &Context<'a, 'tcx>, expr: &hir::Expr)
+        fn get_transmute_from_to<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr)
             -> Option<(&'tcx ty::TypeVariants<'tcx>, &'tcx ty::TypeVariants<'tcx>)> {
             match expr.node {
                 hir::ExprPath(..) => (),
@@ -2538,7 +1156,7 @@ impl LintPass for MutableTransmutes {
             None
         }
 
-        fn def_id_is_transmute(cx: &Context, def_id: DefId) -> bool {
+        fn def_id_is_transmute(cx: &LateContext, def_id: DefId) -> bool {
             match cx.tcx.lookup_item_type(def_id).ty.sty {
                 ty::TyBareFn(_, ref bfty) if bfty.abi == RustIntrinsic => (),
                 _ => return false
@@ -2565,7 +1183,10 @@ impl LintPass for UnstableFeatures {
     fn get_lints(&self) -> LintArray {
         lint_array!(UNSTABLE_FEATURES)
     }
-    fn check_attribute(&mut self, ctx: &Context, attr: &hir::Attribute) {
+}
+
+impl LateLintPass for UnstableFeatures {
+    fn check_attribute(&mut self, ctx: &LateContext, attr: &ast::Attribute) {
         if attr::contains_name(&[attr.node.value.clone()], "feature") {
             if let Some(items) = attr.node.value.meta_item_list() {
                 for item in items {
@@ -2591,8 +1212,10 @@ impl LintPass for DropWithReprExtern {
     fn get_lints(&self) -> LintArray {
         lint_array!(DROP_WITH_REPR_EXTERN)
     }
+}
 
-    fn check_crate(&mut self, ctx: &Context, _: &hir::Crate) {
+impl LateLintPass for DropWithReprExtern {
+    fn check_crate(&mut self, ctx: &LateContext, _: &hir::Crate) {
         let drop_trait = match ctx.tcx.lang_items.drop_trait() {
             Some(id) => ctx.tcx.lookup_trait_def(id), None => { return }
         };
@@ -2613,15 +1236,12 @@ impl LintPass for DropWithReprExtern {
                                                                      codemap::DUMMY_SP);
                         let self_defn_span = ctx.tcx.map.def_id_span(self_type_did,
                                                                      codemap::DUMMY_SP);
-                        ctx.span_lint(DROP_WITH_REPR_EXTERN,
-                                      drop_impl_span,
-                                      "implementing Drop adds hidden state to types, \
-                                       possibly conflicting with `#[repr(C)]`");
-                        // FIXME #19668: could be span_lint_note instead of manual guard.
-                        if ctx.current_level(DROP_WITH_REPR_EXTERN) != Level::Allow {
-                            ctx.sess().span_note(self_defn_span,
-                                               "the `#[repr(C)]` attribute is attached here");
-                        }
+                        ctx.span_lint_note(DROP_WITH_REPR_EXTERN,
+                                           drop_impl_span,
+                                           "implementing Drop adds hidden state to types, \
+                                            possibly conflicting with `#[repr(C)]`",
+                                            self_defn_span,
+                                            "the `#[repr(C)]` attribute is attached here");
                     }
                 }
                 _ => {}
index 517a3d13ddf76d810fcf7b51b6f986a487e5b3d6..920e0341372ba6afa47896911eecb46a6520669e 100644 (file)
@@ -35,7 +35,6 @@
 #![feature(box_syntax)]
 #![feature(num_bits_bytes)]
 #![feature(quote)]
-#![feature(ref_slice)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 #![feature(slice_patterns)]
@@ -48,6 +47,7 @@ extern crate rustc;
 #[macro_use]
 extern crate log;
 extern crate rustc_front;
+extern crate rustc_back;
 
 pub use rustc::lint as lint;
 pub use rustc::metadata as metadata;
@@ -58,7 +58,15 @@ pub use rustc::util as util;
 use session::Session;
 use lint::LintId;
 
+mod bad_style;
 mod builtin;
+mod types;
+mod unused;
+
+use bad_style::*;
+use builtin::*;
+use types::*;
+use unused::*;
 
 /// Tell the `LintStore` about all the built-in lints (the ones
 /// defined in this crate and the ones defined in
@@ -67,7 +75,15 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
     macro_rules! add_builtin {
         ($sess:ident, $($name:ident),*,) => (
             {$(
-                store.register_pass($sess, false, box builtin::$name);
+                store.register_late_pass($sess, false, box $name);
+                )*}
+            )
+    }
+
+    macro_rules! add_early_builtin {
+        ($sess:ident, $($name:ident),*,) => (
+            {$(
+                store.register_early_pass($sess, false, box $name);
                 )*}
             )
     }
@@ -75,17 +91,21 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
     macro_rules! add_builtin_with_new {
         ($sess:ident, $($name:ident),*,) => (
             {$(
-                store.register_pass($sess, false, box builtin::$name::new());
+                store.register_late_pass($sess, false, box $name::new());
                 )*}
             )
     }
 
     macro_rules! add_lint_group {
         ($sess:ident, $name:expr, $($lint:ident),*) => (
-            store.register_group($sess, false, $name, vec![$(LintId::of(builtin::$lint)),*]);
+            store.register_group($sess, false, $name, vec![$(LintId::of($lint)),*]);
             )
     }
 
+    add_early_builtin!(sess,
+                       UnusedParens,
+                       );
+
     add_builtin!(sess,
                  HardwiredLints,
                  WhileTrue,
@@ -97,7 +117,6 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
                  NonCamelCaseTypes,
                  NonSnakeCase,
                  NonUpperCaseGlobals,
-                 UnusedParens,
                  UnusedImportBraces,
                  NonShorthandFieldPatterns,
                  UnusedUnsafe,
@@ -127,10 +146,10 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
     add_lint_group!(sess, "unused",
                     UNUSED_IMPORTS, UNUSED_VARIABLES, UNUSED_ASSIGNMENTS, DEAD_CODE,
                     UNUSED_MUT, UNREACHABLE_CODE, UNUSED_MUST_USE,
-                    UNUSED_UNSAFE, PATH_STATEMENTS);
+                    UNUSED_UNSAFE, PATH_STATEMENTS, UNUSED_ATTRIBUTES);
 
     // We have one lint pass defined specially
-    store.register_pass(sess, false, box lint::GatherNodeLevels);
+    store.register_late_pass(sess, false, box lint::GatherNodeLevels);
 
     // Insert temporary renamings for a one-time deprecation
     store.register_renamed("raw_pointer_deriving", "raw_pointer_derive");
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
new file mode 100644 (file)
index 0000000..264228a
--- /dev/null
@@ -0,0 +1,676 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use middle::{infer};
+use middle::def_id::DefId;
+use middle::subst::Substs;
+use middle::ty::{self, Ty};
+use middle::const_eval::{eval_const_expr_partial, ConstVal};
+use middle::const_eval::EvalHint::ExprTypeChecked;
+use util::nodemap::{FnvHashSet};
+use lint::{LateContext, LintContext, LintArray};
+use lint::{LintPass, LateLintPass};
+
+use std::cmp;
+use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
+
+use syntax::{abi, ast};
+use syntax::attr::{self, AttrMetaMethods};
+use syntax::codemap::{self, Span};
+use syntax::feature_gate::{emit_feature_err, GateIssue};
+use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64};
+
+use rustc_front::hir;
+use rustc_front::visit::{self, Visitor};
+use rustc_front::util::is_shift_binop;
+
+declare_lint! {
+    UNUSED_COMPARISONS,
+    Warn,
+    "comparisons made useless by limits of the types involved"
+}
+
+declare_lint! {
+    OVERFLOWING_LITERALS,
+    Warn,
+    "literal out of range for its type"
+}
+
+declare_lint! {
+    EXCEEDING_BITSHIFTS,
+    Deny,
+    "shift exceeds the type's number of bits"
+}
+
+#[derive(Copy, Clone)]
+pub struct TypeLimits {
+    /// Id of the last visited negated expression
+    negated_expr_id: ast::NodeId,
+}
+
+impl TypeLimits {
+    pub fn new() -> TypeLimits {
+        TypeLimits {
+            negated_expr_id: !0,
+        }
+    }
+}
+
+impl LintPass for TypeLimits {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNUSED_COMPARISONS, OVERFLOWING_LITERALS, EXCEEDING_BITSHIFTS)
+    }
+}
+
+impl LateLintPass for TypeLimits {
+    fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
+        match e.node {
+            hir::ExprUnary(hir::UnNeg, ref expr) => {
+                match expr.node  {
+                    hir::ExprLit(ref lit) => {
+                        match lit.node {
+                            ast::LitInt(_, ast::UnsignedIntLit(_)) => {
+                                check_unsigned_negation_feature(cx, e.span);
+                            },
+                            ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
+                                if let ty::TyUint(_) = cx.tcx.node_id_to_type(e.id).sty {
+                                    check_unsigned_negation_feature(cx, e.span);
+                                }
+                            },
+                            _ => ()
+                        }
+                    },
+                    _ => {
+                        let t = cx.tcx.node_id_to_type(expr.id);
+                        match t.sty {
+                            ty::TyUint(_) => {
+                                check_unsigned_negation_feature(cx, e.span);
+                            },
+                            _ => ()
+                        }
+                    }
+                };
+                // propagate negation, if the negation itself isn't negated
+                if self.negated_expr_id != e.id {
+                    self.negated_expr_id = expr.id;
+                }
+            },
+            hir::ExprBinary(binop, ref l, ref r) => {
+                if is_comparison(binop) && !check_limits(cx.tcx, binop, &**l, &**r) {
+                    cx.span_lint(UNUSED_COMPARISONS, e.span,
+                                 "comparison is useless due to type limits");
+                }
+
+                if is_shift_binop(binop.node) {
+                    let opt_ty_bits = match cx.tcx.node_id_to_type(l.id).sty {
+                        ty::TyInt(t) => Some(int_ty_bits(t, cx.sess().target.int_type)),
+                        ty::TyUint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)),
+                        _ => None
+                    };
+
+                    if let Some(bits) = opt_ty_bits {
+                        let exceeding = if let hir::ExprLit(ref lit) = r.node {
+                            if let ast::LitInt(shift, _) = lit.node { shift >= bits }
+                            else { false }
+                        } else {
+                            match eval_const_expr_partial(cx.tcx, &r, ExprTypeChecked, None) {
+                                Ok(ConstVal::Int(shift)) => { shift as u64 >= bits },
+                                Ok(ConstVal::Uint(shift)) => { shift >= bits },
+                                _ => { false }
+                            }
+                        };
+                        if exceeding {
+                            cx.span_lint(EXCEEDING_BITSHIFTS, e.span,
+                                         "bitshift exceeds the type's number of bits");
+                        }
+                    };
+                }
+            },
+            hir::ExprLit(ref lit) => {
+                match cx.tcx.node_id_to_type(e.id).sty {
+                    ty::TyInt(t) => {
+                        match lit.node {
+                            ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) |
+                            ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => {
+                                let int_type = if let ast::TyIs = t {
+                                    cx.sess().target.int_type
+                                } else {
+                                    t
+                                };
+                                let (_, max) = int_ty_range(int_type);
+                                let negative = self.negated_expr_id == e.id;
+
+                                // Detect literal value out of range [min, max] inclusive
+                                // avoiding use of -min to prevent overflow/panic
+                                if (negative && v > max as u64 + 1) ||
+                                   (!negative && v > max as u64) {
+                                    cx.span_lint(OVERFLOWING_LITERALS, e.span,
+                                                 &*format!("literal out of range for {:?}", t));
+                                    return;
+                                }
+                            }
+                            _ => panic!()
+                        };
+                    },
+                    ty::TyUint(t) => {
+                        let uint_type = if let ast::TyUs = t {
+                            cx.sess().target.uint_type
+                        } else {
+                            t
+                        };
+                        let (min, max) = uint_ty_range(uint_type);
+                        let lit_val: u64 = match lit.node {
+                            ast::LitByte(_v) => return,  // _v is u8, within range by definition
+                            ast::LitInt(v, _) => v,
+                            _ => panic!()
+                        };
+                        if lit_val < min || lit_val > max {
+                            cx.span_lint(OVERFLOWING_LITERALS, e.span,
+                                         &*format!("literal out of range for {:?}", t));
+                        }
+                    },
+                    ty::TyFloat(t) => {
+                        let (min, max) = float_ty_range(t);
+                        let lit_val: f64 = match lit.node {
+                            ast::LitFloat(ref v, _) |
+                            ast::LitFloatUnsuffixed(ref v) => {
+                                match v.parse() {
+                                    Ok(f) => f,
+                                    Err(_) => return
+                                }
+                            }
+                            _ => panic!()
+                        };
+                        if lit_val < min || lit_val > max {
+                            cx.span_lint(OVERFLOWING_LITERALS, e.span,
+                                         &*format!("literal out of range for {:?}", t));
+                        }
+                    },
+                    _ => ()
+                };
+            },
+            _ => ()
+        };
+
+        fn is_valid<T:cmp::PartialOrd>(binop: hir::BinOp, v: T,
+                                min: T, max: T) -> bool {
+            match binop.node {
+                hir::BiLt => v >  min && v <= max,
+                hir::BiLe => v >= min && v <  max,
+                hir::BiGt => v >= min && v <  max,
+                hir::BiGe => v >  min && v <= max,
+                hir::BiEq | hir::BiNe => v >= min && v <= max,
+                _ => panic!()
+            }
+        }
+
+        fn rev_binop(binop: hir::BinOp) -> hir::BinOp {
+            codemap::respan(binop.span, match binop.node {
+                hir::BiLt => hir::BiGt,
+                hir::BiLe => hir::BiGe,
+                hir::BiGt => hir::BiLt,
+                hir::BiGe => hir::BiLe,
+                _ => return binop
+            })
+        }
+
+        // for isize & usize, be conservative with the warnings, so that the
+        // warnings are consistent between 32- and 64-bit platforms
+        fn int_ty_range(int_ty: ast::IntTy) -> (i64, i64) {
+            match int_ty {
+                ast::TyIs => (i64::MIN,        i64::MAX),
+                ast::TyI8 =>    (i8::MIN  as i64, i8::MAX  as i64),
+                ast::TyI16 =>   (i16::MIN as i64, i16::MAX as i64),
+                ast::TyI32 =>   (i32::MIN as i64, i32::MAX as i64),
+                ast::TyI64 =>   (i64::MIN,        i64::MAX)
+            }
+        }
+
+        fn uint_ty_range(uint_ty: ast::UintTy) -> (u64, u64) {
+            match uint_ty {
+                ast::TyUs => (u64::MIN,         u64::MAX),
+                ast::TyU8 =>    (u8::MIN   as u64, u8::MAX   as u64),
+                ast::TyU16 =>   (u16::MIN  as u64, u16::MAX  as u64),
+                ast::TyU32 =>   (u32::MIN  as u64, u32::MAX  as u64),
+                ast::TyU64 =>   (u64::MIN,         u64::MAX)
+            }
+        }
+
+        fn float_ty_range(float_ty: ast::FloatTy) -> (f64, f64) {
+            match float_ty {
+                ast::TyF32 => (f32::MIN as f64, f32::MAX as f64),
+                ast::TyF64 => (f64::MIN,        f64::MAX)
+            }
+        }
+
+        fn int_ty_bits(int_ty: ast::IntTy, target_int_ty: ast::IntTy) -> u64 {
+            match int_ty {
+                ast::TyIs => int_ty_bits(target_int_ty, target_int_ty),
+                ast::TyI8 =>    i8::BITS  as u64,
+                ast::TyI16 =>   i16::BITS as u64,
+                ast::TyI32 =>   i32::BITS as u64,
+                ast::TyI64 =>   i64::BITS as u64
+            }
+        }
+
+        fn uint_ty_bits(uint_ty: ast::UintTy, target_uint_ty: ast::UintTy) -> u64 {
+            match uint_ty {
+                ast::TyUs => uint_ty_bits(target_uint_ty, target_uint_ty),
+                ast::TyU8 =>    u8::BITS  as u64,
+                ast::TyU16 =>   u16::BITS as u64,
+                ast::TyU32 =>   u32::BITS as u64,
+                ast::TyU64 =>   u64::BITS as u64
+            }
+        }
+
+        fn check_limits(tcx: &ty::ctxt, binop: hir::BinOp,
+                        l: &hir::Expr, r: &hir::Expr) -> bool {
+            let (lit, expr, swap) = match (&l.node, &r.node) {
+                (&hir::ExprLit(_), _) => (l, r, true),
+                (_, &hir::ExprLit(_)) => (r, l, false),
+                _ => return true
+            };
+            // Normalize the binop so that the literal is always on the RHS in
+            // the comparison
+            let norm_binop = if swap {
+                rev_binop(binop)
+            } else {
+                binop
+            };
+            match tcx.node_id_to_type(expr.id).sty {
+                ty::TyInt(int_ty) => {
+                    let (min, max) = int_ty_range(int_ty);
+                    let lit_val: i64 = match lit.node {
+                        hir::ExprLit(ref li) => match li.node {
+                            ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) |
+                            ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => v as i64,
+                            ast::LitInt(v, ast::SignedIntLit(_, ast::Minus)) |
+                            ast::LitInt(v, ast::UnsuffixedIntLit(ast::Minus)) => -(v as i64),
+                            _ => return true
+                        },
+                        _ => panic!()
+                    };
+                    is_valid(norm_binop, lit_val, min, max)
+                }
+                ty::TyUint(uint_ty) => {
+                    let (min, max): (u64, u64) = uint_ty_range(uint_ty);
+                    let lit_val: u64 = match lit.node {
+                        hir::ExprLit(ref li) => match li.node {
+                            ast::LitInt(v, _) => v,
+                            _ => return true
+                        },
+                        _ => panic!()
+                    };
+                    is_valid(norm_binop, lit_val, min, max)
+                }
+                _ => true
+            }
+        }
+
+        fn is_comparison(binop: hir::BinOp) -> bool {
+            match binop.node {
+                hir::BiEq | hir::BiLt | hir::BiLe |
+                hir::BiNe | hir::BiGe | hir::BiGt => true,
+                _ => false
+            }
+        }
+
+        fn check_unsigned_negation_feature(cx: &LateContext, span: Span) {
+            if !cx.sess().features.borrow().negate_unsigned {
+                emit_feature_err(
+                    &cx.sess().parse_sess.span_diagnostic,
+                    "negate_unsigned",
+                    span,
+                    GateIssue::Language,
+                    "unary negation of unsigned integers may be removed in the future");
+            }
+        }
+    }
+}
+
+declare_lint! {
+    IMPROPER_CTYPES,
+    Warn,
+    "proper use of libc types in foreign modules"
+}
+
+struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
+    cx: &'a LateContext<'a, 'tcx>
+}
+
+enum FfiResult {
+    FfiSafe,
+    FfiUnsafe(&'static str),
+    FfiBadStruct(DefId, &'static str),
+    FfiBadEnum(DefId, &'static str)
+}
+
+/// Check if this enum can be safely exported based on the
+/// "nullable pointer optimization". Currently restricted
+/// to function pointers and references, but could be
+/// expanded to cover NonZero raw pointers and newtypes.
+/// FIXME: This duplicates code in trans.
+fn is_repr_nullable_ptr<'tcx>(tcx: &ty::ctxt<'tcx>,
+                              def: ty::AdtDef<'tcx>,
+                              substs: &Substs<'tcx>)
+                              -> bool {
+    if def.variants.len() == 2 {
+        let data_idx;
+
+        if def.variants[0].fields.is_empty() {
+            data_idx = 1;
+        } else if def.variants[1].fields.is_empty() {
+            data_idx = 0;
+        } else {
+            return false;
+        }
+
+        if def.variants[data_idx].fields.len() == 1 {
+            match def.variants[data_idx].fields[0].ty(tcx, substs).sty {
+                ty::TyBareFn(None, _) => { return true; }
+                ty::TyRef(..) => { return true; }
+                _ => { }
+            }
+        }
+    }
+    false
+}
+
+fn ast_ty_to_normalized<'tcx>(tcx: &ty::ctxt<'tcx>,
+                              id: ast::NodeId)
+                              -> Ty<'tcx> {
+    let tty = match tcx.ast_ty_to_ty_cache.borrow().get(&id) {
+        Some(&t) => t,
+        None => panic!("ast_ty_to_ty_cache was incomplete after typeck!")
+    };
+    infer::normalize_associated_type(tcx, &tty)
+}
+
+impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
+    /// Check if the given type is "ffi-safe" (has a stable, well-defined
+    /// representation which can be exported to C code).
+    fn check_type_for_ffi(&self,
+                          cache: &mut FnvHashSet<Ty<'tcx>>,
+                          ty: Ty<'tcx>)
+                          -> FfiResult {
+        use self::FfiResult::*;
+        let cx = &self.cx.tcx;
+
+        // Protect against infinite recursion, for example
+        // `struct S(*mut S);`.
+        // FIXME: A recursion limit is necessary as well, for irregular
+        // recusive types.
+        if !cache.insert(ty) {
+            return FfiSafe;
+        }
+
+        match ty.sty {
+            ty::TyStruct(def, substs) => {
+                if !cx.lookup_repr_hints(def.did).contains(&attr::ReprExtern) {
+                    return FfiUnsafe(
+                        "found struct without foreign-function-safe \
+                         representation annotation in foreign module, \
+                         consider adding a #[repr(C)] attribute to \
+                         the type");
+                }
+
+                // We can't completely trust repr(C) markings; make sure the
+                // fields are actually safe.
+                if def.struct_variant().fields.is_empty() {
+                    return FfiUnsafe(
+                        "found zero-size struct in foreign module, consider \
+                         adding a member to this struct");
+                }
+
+                for field in &def.struct_variant().fields {
+                    let field_ty = infer::normalize_associated_type(cx, &field.ty(cx, substs));
+                    let r = self.check_type_for_ffi(cache, field_ty);
+                    match r {
+                        FfiSafe => {}
+                        FfiBadStruct(..) | FfiBadEnum(..) => { return r; }
+                        FfiUnsafe(s) => { return FfiBadStruct(def.did, s); }
+                    }
+                }
+                FfiSafe
+            }
+            ty::TyEnum(def, substs) => {
+                if def.variants.is_empty() {
+                    // Empty enums are okay... although sort of useless.
+                    return FfiSafe
+                }
+
+                // Check for a repr() attribute to specify the size of the
+                // discriminant.
+                let repr_hints = cx.lookup_repr_hints(def.did);
+                match &**repr_hints {
+                    [] => {
+                        // Special-case types like `Option<extern fn()>`.
+                        if !is_repr_nullable_ptr(cx, def, substs) {
+                            return FfiUnsafe(
+                                "found enum without foreign-function-safe \
+                                 representation annotation in foreign module, \
+                                 consider adding a #[repr(...)] attribute to \
+                                 the type")
+                        }
+                    }
+                    [ref hint] => {
+                        if !hint.is_ffi_safe() {
+                            // FIXME: This shouldn't be reachable: we should check
+                            // this earlier.
+                            return FfiUnsafe(
+                                "enum has unexpected #[repr(...)] attribute")
+                        }
+
+                        // Enum with an explicitly sized discriminant; either
+                        // a C-style enum or a discriminated union.
+
+                        // The layout of enum variants is implicitly repr(C).
+                        // FIXME: Is that correct?
+                    }
+                    _ => {
+                        // FIXME: This shouldn't be reachable: we should check
+                        // this earlier.
+                        return FfiUnsafe(
+                            "enum has too many #[repr(...)] attributes");
+                    }
+                }
+
+                // Check the contained variants.
+                for variant in &def.variants {
+                    for field in &variant.fields {
+                        let arg = infer::normalize_associated_type(cx, &field.ty(cx, substs));
+                        let r = self.check_type_for_ffi(cache, arg);
+                        match r {
+                            FfiSafe => {}
+                            FfiBadStruct(..) | FfiBadEnum(..) => { return r; }
+                            FfiUnsafe(s) => { return FfiBadEnum(def.did, s); }
+                        }
+                    }
+                }
+                FfiSafe
+            }
+
+            ty::TyChar => {
+                FfiUnsafe("found Rust type `char` in foreign module, while \
+                           `u32` or `libc::wchar_t` should be used")
+            }
+
+            // Primitive types with a stable representation.
+            ty::TyBool | ty::TyInt(..) | ty::TyUint(..) |
+            ty::TyFloat(..) => FfiSafe,
+
+            ty::TyBox(..) => {
+                FfiUnsafe("found Rust type Box<_> in foreign module, \
+                           consider using a raw pointer instead")
+            }
+
+            ty::TySlice(_) => {
+                FfiUnsafe("found Rust slice type in foreign module, \
+                           consider using a raw pointer instead")
+            }
+
+            ty::TyTrait(..) => {
+                FfiUnsafe("found Rust trait type in foreign module, \
+                           consider using a raw pointer instead")
+            }
+
+            ty::TyStr => {
+                FfiUnsafe("found Rust type `str` in foreign module; \
+                           consider using a `*const libc::c_char`")
+            }
+
+            ty::TyTuple(_) => {
+                FfiUnsafe("found Rust tuple type in foreign module; \
+                           consider using a struct instead`")
+            }
+
+            ty::TyRawPtr(ref m) | ty::TyRef(_, ref m) => {
+                self.check_type_for_ffi(cache, m.ty)
+            }
+
+            ty::TyArray(ty, _) => {
+                self.check_type_for_ffi(cache, ty)
+            }
+
+            ty::TyBareFn(None, bare_fn) => {
+                match bare_fn.abi {
+                    abi::Rust |
+                    abi::RustIntrinsic |
+                    abi::PlatformIntrinsic |
+                    abi::RustCall => {
+                        return FfiUnsafe(
+                            "found function pointer with Rust calling \
+                             convention in foreign module; consider using an \
+                             `extern` function pointer")
+                    }
+                    _ => {}
+                }
+
+                let sig = cx.erase_late_bound_regions(&bare_fn.sig);
+                match sig.output {
+                    ty::FnDiverging => {}
+                    ty::FnConverging(output) => {
+                        if !output.is_nil() {
+                            let r = self.check_type_for_ffi(cache, output);
+                            match r {
+                                FfiSafe => {}
+                                _ => { return r; }
+                            }
+                        }
+                    }
+                }
+                for arg in sig.inputs {
+                    let r = self.check_type_for_ffi(cache, arg);
+                    match r {
+                        FfiSafe => {}
+                        _ => { return r; }
+                    }
+                }
+                FfiSafe
+            }
+
+            ty::TyParam(..) | ty::TyInfer(..) | ty::TyError |
+            ty::TyClosure(..) | ty::TyProjection(..) |
+            ty::TyBareFn(Some(_), _) => {
+                panic!("Unexpected type in foreign function")
+            }
+        }
+    }
+
+    fn check_def(&mut self, sp: Span, id: ast::NodeId) {
+        let tty = ast_ty_to_normalized(self.cx.tcx, id);
+
+        match ImproperCTypesVisitor::check_type_for_ffi(self, &mut FnvHashSet(), tty) {
+            FfiResult::FfiSafe => {}
+            FfiResult::FfiUnsafe(s) => {
+                self.cx.span_lint(IMPROPER_CTYPES, sp, s);
+            }
+            FfiResult::FfiBadStruct(_, s) => {
+                // FIXME: This diagnostic is difficult to read, and doesn't
+                // point at the relevant field.
+                self.cx.span_lint(IMPROPER_CTYPES, sp,
+                    &format!("found non-foreign-function-safe member in \
+                              struct marked #[repr(C)]: {}", s));
+            }
+            FfiResult::FfiBadEnum(_, s) => {
+                // FIXME: This diagnostic is difficult to read, and doesn't
+                // point at the relevant variant.
+                self.cx.span_lint(IMPROPER_CTYPES, sp,
+                    &format!("found non-foreign-function-safe member in \
+                              enum: {}", s));
+            }
+        }
+    }
+}
+
+impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> {
+    fn visit_ty(&mut self, ty: &hir::Ty) {
+        match ty.node {
+            hir::TyPath(..) |
+            hir::TyBareFn(..) => self.check_def(ty.span, ty.id),
+            hir::TyVec(..) => {
+                self.cx.span_lint(IMPROPER_CTYPES, ty.span,
+                    "found Rust slice type in foreign module, consider \
+                     using a raw pointer instead");
+            }
+            hir::TyFixedLengthVec(ref ty, _) => self.visit_ty(ty),
+            hir::TyTup(..) => {
+                self.cx.span_lint(IMPROPER_CTYPES, ty.span,
+                    "found Rust tuple type in foreign module; \
+                     consider using a struct instead`")
+            }
+            _ => visit::walk_ty(self, ty)
+        }
+    }
+}
+
+#[derive(Copy, Clone)]
+pub struct ImproperCTypes;
+
+impl LintPass for ImproperCTypes {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(IMPROPER_CTYPES)
+    }
+}
+
+impl LateLintPass for ImproperCTypes {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+        fn check_ty(cx: &LateContext, ty: &hir::Ty) {
+            let mut vis = ImproperCTypesVisitor { cx: cx };
+            vis.visit_ty(ty);
+        }
+
+        fn check_foreign_fn(cx: &LateContext, decl: &hir::FnDecl) {
+            for input in &decl.inputs {
+                check_ty(cx, &*input.ty);
+            }
+            if let hir::Return(ref ret_ty) = decl.output {
+                let tty = ast_ty_to_normalized(cx.tcx, ret_ty.id);
+                if !tty.is_nil() {
+                    check_ty(cx, &ret_ty);
+                }
+            }
+        }
+
+        match it.node {
+            hir::ItemForeignMod(ref nmod)
+                if nmod.abi != abi::RustIntrinsic &&
+                   nmod.abi != abi::PlatformIntrinsic => {
+                for ni in &nmod.items {
+                    match ni.node {
+                        hir::ForeignItemFn(ref decl, _) => check_foreign_fn(cx, &**decl),
+                        hir::ForeignItemStatic(ref t, _) => check_ty(cx, &**t)
+                    }
+                }
+            }
+            _ => (),
+        }
+    }
+}
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
new file mode 100644 (file)
index 0000000..8ed4706
--- /dev/null
@@ -0,0 +1,465 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use metadata::csearch;
+use middle::pat_util;
+use middle::ty;
+use middle::ty::adjustment;
+use rustc::front::map as hir_map;
+use util::nodemap::FnvHashMap;
+use lint::{LateContext, EarlyContext, LintContext, LintArray};
+use lint::{LintPass, EarlyLintPass, LateLintPass};
+
+use std::collections::hash_map::Entry::{Occupied, Vacant};
+
+use syntax::ast;
+use syntax::attr::{self, AttrMetaMethods};
+use syntax::codemap::Span;
+use syntax::feature_gate::{KNOWN_ATTRIBUTES, AttributeType};
+use syntax::ptr::P;
+
+use rustc_back::slice;
+use rustc_front::hir;
+use rustc_front::visit::FnKind;
+
+declare_lint! {
+    pub UNUSED_MUT,
+    Warn,
+    "detect mut variables which don't need to be mutable"
+}
+
+#[derive(Copy, Clone)]
+pub struct UnusedMut;
+
+impl UnusedMut {
+    fn check_unused_mut_pat(&self, cx: &LateContext, pats: &[P<hir::Pat>]) {
+        // collect all mutable pattern and group their NodeIDs by their Identifier to
+        // avoid false warnings in match arms with multiple patterns
+
+        let mut mutables = FnvHashMap();
+        for p in pats {
+            pat_util::pat_bindings(&cx.tcx.def_map, p, |mode, id, _, path1| {
+                let name = path1.node;
+                if let hir::BindByValue(hir::MutMutable) = mode {
+                    if !name.as_str().starts_with("_") {
+                        match mutables.entry(name.0 as usize) {
+                            Vacant(entry) => { entry.insert(vec![id]); },
+                            Occupied(mut entry) => { entry.get_mut().push(id); },
+                        }
+                    }
+                }
+            });
+        }
+
+        let used_mutables = cx.tcx.used_mut_nodes.borrow();
+        for (_, v) in &mutables {
+            if !v.iter().any(|e| used_mutables.contains(e)) {
+                cx.span_lint(UNUSED_MUT, cx.tcx.map.span(v[0]),
+                             "variable does not need to be mutable");
+            }
+        }
+    }
+}
+
+impl LintPass for UnusedMut {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNUSED_MUT)
+    }
+}
+
+impl LateLintPass for UnusedMut {
+    fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
+        if let hir::ExprMatch(_, ref arms, _) = e.node {
+            for a in arms {
+                self.check_unused_mut_pat(cx, &a.pats)
+            }
+        }
+    }
+
+    fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
+        if let hir::StmtDecl(ref d, _) = s.node {
+            if let hir::DeclLocal(ref l) = d.node {
+                self.check_unused_mut_pat(cx, slice::ref_slice(&l.pat));
+            }
+        }
+    }
+
+    fn check_fn(&mut self, cx: &LateContext,
+                _: FnKind, decl: &hir::FnDecl,
+                _: &hir::Block, _: Span, _: ast::NodeId) {
+        for a in &decl.inputs {
+            self.check_unused_mut_pat(cx, slice::ref_slice(&a.pat));
+        }
+    }
+}
+
+declare_lint! {
+    pub UNUSED_MUST_USE,
+    Warn,
+    "unused result of a type flagged as #[must_use]"
+}
+
+declare_lint! {
+    pub UNUSED_RESULTS,
+    Allow,
+    "unused result of an expression in a statement"
+}
+
+#[derive(Copy, Clone)]
+pub struct UnusedResults;
+
+impl LintPass for UnusedResults {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNUSED_MUST_USE, UNUSED_RESULTS)
+    }
+}
+
+impl LateLintPass for UnusedResults {
+    fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
+        let expr = match s.node {
+            hir::StmtSemi(ref expr, _) => &**expr,
+            _ => return
+        };
+
+        if let hir::ExprRet(..) = expr.node {
+            return;
+        }
+
+        let t = cx.tcx.expr_ty(&expr);
+        let warned = match t.sty {
+            ty::TyTuple(ref tys) if tys.is_empty() => return,
+            ty::TyBool => return,
+            ty::TyStruct(def, _) |
+            ty::TyEnum(def, _) => {
+                if let Some(def_node_id) = cx.tcx.map.as_local_node_id(def.did) {
+                    if let hir_map::NodeItem(it) = cx.tcx.map.get(def_node_id) {
+                        check_must_use(cx, &it.attrs, s.span)
+                    } else {
+                        false
+                    }
+                } else {
+                    let attrs = csearch::get_item_attrs(&cx.sess().cstore, def.did);
+                    check_must_use(cx, &attrs[..], s.span)
+                }
+            }
+            _ => false,
+        };
+        if !warned {
+            cx.span_lint(UNUSED_RESULTS, s.span, "unused result");
+        }
+
+        fn check_must_use(cx: &LateContext, attrs: &[ast::Attribute], sp: Span) -> bool {
+            for attr in attrs {
+                if attr.check_name("must_use") {
+                    let mut msg = "unused result which must be used".to_string();
+                    // check for #[must_use="..."]
+                    match attr.value_str() {
+                        None => {}
+                        Some(s) => {
+                            msg.push_str(": ");
+                            msg.push_str(&s);
+                        }
+                    }
+                    cx.span_lint(UNUSED_MUST_USE, sp, &msg);
+                    return true;
+                }
+            }
+            false
+        }
+    }
+}
+
+declare_lint! {
+    pub UNUSED_UNSAFE,
+    Warn,
+    "unnecessary use of an `unsafe` block"
+}
+
+#[derive(Copy, Clone)]
+pub struct UnusedUnsafe;
+
+impl LintPass for UnusedUnsafe {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNUSED_UNSAFE)
+    }
+}
+
+impl LateLintPass for UnusedUnsafe {
+    fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
+        if let hir::ExprBlock(ref blk) = e.node {
+            // Don't warn about generated blocks, that'll just pollute the output.
+            if blk.rules == hir::UnsafeBlock(hir::UserProvided) &&
+                !cx.tcx.used_unsafe.borrow().contains(&blk.id) {
+                    cx.span_lint(UNUSED_UNSAFE, blk.span, "unnecessary `unsafe` block");
+            }
+        }
+    }
+}
+
+declare_lint! {
+    pub PATH_STATEMENTS,
+    Warn,
+    "path statements with no effect"
+}
+
+#[derive(Copy, Clone)]
+pub struct PathStatements;
+
+impl LintPass for PathStatements {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(PATH_STATEMENTS)
+    }
+}
+
+impl LateLintPass for PathStatements {
+    fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
+        match s.node {
+            hir::StmtSemi(ref expr, _) => {
+                match expr.node {
+                    hir::ExprPath(..) => cx.span_lint(PATH_STATEMENTS, s.span,
+                                                      "path statement with no effect"),
+                    _ => ()
+                }
+            }
+            _ => ()
+        }
+    }
+}
+
+declare_lint! {
+    pub UNUSED_ATTRIBUTES,
+    Warn,
+    "detects attributes that were not used by the compiler"
+}
+
+#[derive(Copy, Clone)]
+pub struct UnusedAttributes;
+
+impl LintPass for UnusedAttributes {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNUSED_ATTRIBUTES)
+    }
+}
+
+impl LateLintPass for UnusedAttributes {
+    fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) {
+        // Note that check_name() marks the attribute as used if it matches.
+        for &(ref name, ty, _) in KNOWN_ATTRIBUTES {
+            match ty {
+                AttributeType::Whitelisted if attr.check_name(name) => {
+                    break;
+                },
+                _ => ()
+            }
+        }
+
+        let plugin_attributes = cx.sess().plugin_attributes.borrow_mut();
+        for &(ref name, ty) in plugin_attributes.iter() {
+            if ty == AttributeType::Whitelisted && attr.check_name(&*name) {
+                break;
+            }
+        }
+
+        if !attr::is_used(attr) {
+            cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
+            // Is it a builtin attribute that must be used at the crate level?
+            let known_crate = KNOWN_ATTRIBUTES.iter().find(|&&(name, ty, _)| {
+                attr.name() == name &&
+                ty == AttributeType::CrateLevel
+            }).is_some();
+
+            // Has a plugin registered this attribute as one which must be used at
+            // the crate level?
+            let plugin_crate = plugin_attributes.iter()
+                                                .find(|&&(ref x, t)| {
+                                                        &*attr.name() == &*x &&
+                                                        AttributeType::CrateLevel == t
+                                                    }).is_some();
+            if  known_crate || plugin_crate {
+                let msg = match attr.node.style {
+                    ast::AttrStyle::Outer => "crate-level attribute should be an inner \
+                                              attribute: add an exclamation mark: #![foo]",
+                    ast::AttrStyle::Inner => "crate-level attribute should be in the \
+                                              root module",
+                };
+                cx.span_lint(UNUSED_ATTRIBUTES, attr.span, msg);
+            }
+        }
+    }
+}
+
+declare_lint! {
+    UNUSED_PARENS,
+    Warn,
+    "`if`, `match`, `while` and `return` do not need parentheses"
+}
+
+#[derive(Copy, Clone)]
+pub struct UnusedParens;
+
+impl UnusedParens {
+    fn check_unused_parens_core(&self, cx: &EarlyContext, value: &ast::Expr, msg: &str,
+                                struct_lit_needs_parens: bool) {
+        if let ast::ExprParen(ref inner) = value.node {
+            let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&**inner);
+            if !necessary {
+                cx.span_lint(UNUSED_PARENS, value.span,
+                             &format!("unnecessary parentheses around {}", msg))
+            }
+        }
+
+        /// Expressions that syntactically contain an "exterior" struct
+        /// literal i.e. not surrounded by any parens or other
+        /// delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo
+        /// == X { y: 1 }` and `X { y: 1 } == foo` all do, but `(X {
+        /// y: 1 }) == foo` does not.
+        fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
+            match value.node {
+                ast::ExprStruct(..) => true,
+
+                ast::ExprAssign(ref lhs, ref rhs) |
+                ast::ExprAssignOp(_, ref lhs, ref rhs) |
+                ast::ExprBinary(_, ref lhs, ref rhs) => {
+                    // X { y: 1 } + X { y: 2 }
+                    contains_exterior_struct_lit(&**lhs) ||
+                        contains_exterior_struct_lit(&**rhs)
+                }
+                ast::ExprUnary(_, ref x) |
+                ast::ExprCast(ref x, _) |
+                ast::ExprField(ref x, _) |
+                ast::ExprTupField(ref x, _) |
+                ast::ExprIndex(ref x, _) => {
+                    // &X { y: 1 }, X { y: 1 }.y
+                    contains_exterior_struct_lit(&**x)
+                }
+
+                ast::ExprMethodCall(_, _, ref exprs) => {
+                    // X { y: 1 }.bar(...)
+                    contains_exterior_struct_lit(&*exprs[0])
+                }
+
+                _ => false
+            }
+        }
+    }
+}
+
+impl LintPass for UnusedParens {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNUSED_PARENS)
+    }
+}
+
+impl EarlyLintPass for UnusedParens {
+    fn check_expr(&mut self, cx: &EarlyContext, e: &ast::Expr) {
+        let (value, msg, struct_lit_needs_parens) = match e.node {
+            ast::ExprIf(ref cond, _, _) => (cond, "`if` condition", true),
+            ast::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true),
+            ast::ExprIfLet(_, ref cond, _, _) => (cond, "`if let` head expression", true),
+            ast::ExprWhileLet(_, ref cond, _, _) => (cond, "`while let` head expression", true),
+            ast::ExprForLoop(_, ref cond, _, _) => (cond, "`for` head expression", true),
+            ast::ExprMatch(ref head, _) => (head, "`match` head expression", true),
+            ast::ExprRet(Some(ref value)) => (value, "`return` value", false),
+            ast::ExprAssign(_, ref value) => (value, "assigned value", false),
+            ast::ExprAssignOp(_, _, ref value) => (value, "assigned value", false),
+            _ => return
+        };
+        self.check_unused_parens_core(cx, &**value, msg, struct_lit_needs_parens);
+    }
+
+    fn check_stmt(&mut self, cx: &EarlyContext, s: &ast::Stmt) {
+        let (value, msg) = match s.node {
+            ast::StmtDecl(ref decl, _) => match decl.node {
+                ast::DeclLocal(ref local) => match local.init {
+                    Some(ref value) => (value, "assigned value"),
+                    None => return
+                },
+                _ => return
+            },
+            _ => return
+        };
+        self.check_unused_parens_core(cx, &**value, msg, false);
+    }
+}
+
+declare_lint! {
+    UNUSED_IMPORT_BRACES,
+    Allow,
+    "unnecessary braces around an imported item"
+}
+
+#[derive(Copy, Clone)]
+pub struct UnusedImportBraces;
+
+impl LintPass for UnusedImportBraces {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNUSED_IMPORT_BRACES)
+    }
+}
+
+impl LateLintPass for UnusedImportBraces {
+    fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
+        if let hir::ItemUse(ref view_path) = item.node {
+            if let hir::ViewPathList(_, ref items) = view_path.node {
+                if items.len() == 1 {
+                    if let hir::PathListIdent {ref name, ..} = items[0].node {
+                        let m = format!("braces around {} is unnecessary",
+                                        name);
+                        cx.span_lint(UNUSED_IMPORT_BRACES, item.span,
+                                     &m[..]);
+                    }
+                }
+            }
+        }
+    }
+}
+
+declare_lint! {
+    UNUSED_ALLOCATION,
+    Warn,
+    "detects unnecessary allocations that can be eliminated"
+}
+
+#[derive(Copy, Clone)]
+pub struct UnusedAllocation;
+
+impl LintPass for UnusedAllocation {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNUSED_ALLOCATION)
+    }
+}
+
+impl LateLintPass for UnusedAllocation {
+    fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
+        match e.node {
+            hir::ExprBox(_) => {}
+            _ => return
+        }
+
+        if let Some(adjustment) = cx.tcx.tables.borrow().adjustments.get(&e.id) {
+            if let adjustment::AdjustDerefRef(adjustment::AutoDerefRef {
+                ref autoref, ..
+            }) = *adjustment {
+                match autoref {
+                    &Some(adjustment::AutoPtr(_, hir::MutImmutable)) => {
+                        cx.span_lint(UNUSED_ALLOCATION, e.span,
+                                     "unnecessary allocation, use & instead");
+                    }
+                    &Some(adjustment::AutoPtr(_, hir::MutMutable)) => {
+                        cx.span_lint(UNUSED_ALLOCATION, e.span,
+                                     "unnecessary allocation, use &mut instead");
+                    }
+                    _ => ()
+                }
+            }
+        }
+    }
+}
+
index aa3a991b8b6d4ffdc87c10777537371fbdf352cd..fe84cffa8c660cecf0540bd0f9c53892b67b4769 100644 (file)
@@ -60,7 +60,7 @@ pub use self::DLLStorageClassTypes::*;
 
 use std::ffi::CString;
 use std::cell::RefCell;
-use std::{slice, mem};
+use std::slice;
 use libc::{c_uint, c_ushort, uint64_t, c_int, size_t, c_char};
 use libc::{c_longlong, c_ulonglong, c_void};
 use debuginfo::{DIBuilderRef, DIDescriptor,
@@ -2307,7 +2307,7 @@ pub unsafe extern "C" fn rust_llvm_string_write_impl(sr: RustStringRef,
                                                      size: size_t) {
     let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
 
-    let sr: RustStringRepr = mem::transmute(sr);
+    let sr = sr as RustStringRepr;
     (*sr).borrow_mut().push_all(slice);
 }
 
index 5604c78e098d81a4d433677cce4721a3f980943f..21a77bbd232af528510bc35141ef5f00cc475ac8 100644 (file)
@@ -8,15 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use build::{BlockAnd, Builder};
 use hair::*;
 use repr::*;
-use build::{BlockAnd, Builder};
+use rustc_front::hir;
 
-impl<H:Hair> Builder<H> {
+impl<'a,'tcx> Builder<'a,'tcx> {
     pub fn ast_block(&mut self,
-                     destination: &Lvalue<H>,
+                     destination: &Lvalue<'tcx>,
                      mut block: BasicBlock,
-                     ast_block: H::Block)
+                     ast_block: &'tcx hir::Block)
                      -> BlockAnd<()> {
         let this = self;
         let Block { extent, span: _, stmts, expr } = this.hir.mirror(ast_block);
index 955e1b7146a46fc6881f20d8af46620c4a80722e..318ae704089f52c0bf43fe501b4417599c72299c 100644 (file)
 //! Routines for manipulating the control-flow graph.
 
 use build::CFG;
-use hair::*;
 use repr::*;
+use syntax::codemap::Span;
 
-impl<H:Hair> CFG<H> {
-    pub fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<H> {
+impl<'tcx> CFG<'tcx> {
+    pub fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> {
         &self.basic_blocks[blk.index()]
     }
 
-    pub fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<H> {
+    pub fn block_data_mut(&mut self, blk: BasicBlock) -> &mut BasicBlockData<'tcx> {
         &mut self.basic_blocks[blk.index()]
     }
 
     pub fn end_point(&self, block: BasicBlock) -> ExecutionPoint {
         ExecutionPoint {
             block: block,
-            statement: self.block_data(block).statements.len() as u32
+            statement: self.block_data(block).statements.len() as u32,
         }
     }
 
@@ -39,21 +39,21 @@ impl<H:Hair> CFG<H> {
         BasicBlock::new(node_index)
     }
 
-    pub fn push(&mut self, block: BasicBlock, statement: Statement<H>) {
+    pub fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) {
         debug!("push({:?}, {:?})", block, statement);
         self.block_data_mut(block).statements.push(statement);
     }
 
     pub fn push_assign_constant(&mut self,
                                 block: BasicBlock,
-                                span: H::Span,
-                                temp: &Lvalue<H>,
-                                constant: Constant<H>) {
+                                span: Span,
+                                temp: &Lvalue<'tcx>,
+                                constant: Constant<'tcx>) {
         self.push_assign(block, span, temp, Rvalue::Use(Operand::Constant(constant)));
     }
 
-    pub fn push_drop(&mut self, block: BasicBlock, span: H::Span,
-                     kind: DropKind, lvalue: &Lvalue<H>) {
+    pub fn push_drop(&mut self, block: BasicBlock, span: Span,
+                     kind: DropKind, lvalue: &Lvalue<'tcx>) {
         self.push(block, Statement {
             span: span,
             kind: StatementKind::Drop(kind, lvalue.clone())
@@ -62,9 +62,9 @@ impl<H:Hair> CFG<H> {
 
     pub fn push_assign(&mut self,
                        block: BasicBlock,
-                       span: H::Span,
-                       lvalue: &Lvalue<H>,
-                       rvalue: Rvalue<H>) {
+                       span: Span,
+                       lvalue: &Lvalue<'tcx>,
+                       rvalue: Rvalue<'tcx>) {
         self.push(block, Statement {
             span: span,
             kind: StatementKind::Assign(lvalue.clone(), rvalue)
@@ -73,7 +73,7 @@ impl<H:Hair> CFG<H> {
 
     pub fn terminate(&mut self,
                      block: BasicBlock,
-                     terminator: Terminator<H>) {
+                     terminator: Terminator<'tcx>) {
         // Check whether this block has already been terminated. For
         // this, we rely on the fact that the initial state is to have
         // a Diverge terminator and an empty list of targets (which
index a6d06c447a4c0efba77214fce174a150d87dc5aa..b362f981764203dce13aaf9a5f672ad6d56290e0 100644 (file)
 
 //! See docs in build/expr/mod.rs
 
-use rustc_data_structures::fnv::FnvHashMap;
-
-use build::{Builder};
+use build::Builder;
 use hair::*;
 use repr::*;
 
-impl<H:Hair> Builder<H> {
+impl<'a,'tcx> Builder<'a,'tcx> {
     /// Compile `expr`, yielding a compile-time constant. Assumes that
     /// `expr` is a valid compile-time constant!
-    pub fn as_constant<M>(&mut self, expr: M) -> Constant<H>
-        where M: Mirror<H, Output=Expr<H>>
+    pub fn as_constant<M>(&mut self, expr: M) -> Constant<'tcx>
+        where M: Mirror<'tcx, Output=Expr<'tcx>>
     {
         let expr = self.hir.mirror(expr);
         self.expr_as_constant(expr)
     }
 
-    fn expr_as_constant(&mut self, expr: Expr<H>) -> Constant<H> {
+    fn expr_as_constant(&mut self, expr: Expr<'tcx>) -> Constant<'tcx> {
         let this = self;
-        let Expr { ty: _, temp_lifetime: _, span, kind } = expr;
-        let kind = match kind {
-            ExprKind::Scope { extent: _, value } => {
-                return this.as_constant(value);
-            }
-            ExprKind::Paren { arg } => {
-                return this.as_constant(arg);
-            }
-            ExprKind::Literal { literal } => {
-                ConstantKind::Literal(literal)
-            }
-            ExprKind::Vec { fields } => {
-                let fields = this.as_constants(fields);
-                ConstantKind::Aggregate(AggregateKind::Vec, fields)
-            }
-            ExprKind::Tuple { fields } => {
-                let fields = this.as_constants(fields);
-                ConstantKind::Aggregate(AggregateKind::Tuple, fields)
-            }
-            ExprKind::Adt { adt_def, variant_index, substs, fields, base: None } => {
-                let field_names = this.hir.fields(adt_def, variant_index);
-                let fields = this.named_field_constants(field_names, fields);
-                ConstantKind::Aggregate(AggregateKind::Adt(adt_def, variant_index, substs), fields)
-            }
-            ExprKind::Repeat { value, count } => {
-                let value = Box::new(this.as_constant(value));
-                let count = Box::new(this.as_constant(count));
-                ConstantKind::Repeat(value, count)
-            }
-            ExprKind::Binary { op, lhs, rhs } => {
-                let lhs = Box::new(this.as_constant(lhs));
-                let rhs = Box::new(this.as_constant(rhs));
-                ConstantKind::BinaryOp(op, lhs, rhs)
-            }
-            ExprKind::Unary { op, arg } => {
-                let arg = Box::new(this.as_constant(arg));
-                ConstantKind::UnaryOp(op, arg)
-            }
-            ExprKind::Field { lhs, name } => {
-                let lhs = this.as_constant(lhs);
-                ConstantKind::Projection(
-                    Box::new(ConstantProjection {
-                        base: lhs,
-                        elem: ProjectionElem::Field(name),
-                    }))
-            }
-            ExprKind::Deref { arg } => {
-                let arg = this.as_constant(arg);
-                ConstantKind::Projection(
-                    Box::new(ConstantProjection {
-                        base: arg,
-                        elem: ProjectionElem::Deref,
-                    }))
-            }
-            ExprKind::Call { fun, args } => {
-                let fun = this.as_constant(fun);
-                let args = this.as_constants(args);
-                ConstantKind::Call(Box::new(fun), args)
-            }
-            _ => {
+        let Expr { ty, temp_lifetime: _, span, kind } = expr;
+        match kind {
+            ExprKind::Scope { extent: _, value } =>
+                this.as_constant(value),
+            ExprKind::Literal { literal } =>
+                Constant { span: span, ty: ty, literal: literal },
+            _ =>
                 this.hir.span_bug(
                     span,
-                    &format!("expression is not a valid constant {:?}", kind));
-            }
-        };
-        Constant { span: span, kind: kind }
-    }
-
-    fn as_constants(&mut self,
-                    exprs: Vec<ExprRef<H>>)
-                    -> Vec<Constant<H>>
-    {
-        exprs.into_iter().map(|expr| self.as_constant(expr)).collect()
-    }
-
-    fn named_field_constants(&mut self,
-                             field_names: Vec<Field<H>>,
-                             field_exprs: Vec<FieldExprRef<H>>)
-                             -> Vec<Constant<H>>
-    {
-        let fields_map: FnvHashMap<_, _> =
-            field_exprs.into_iter()
-                       .map(|f| (f.name, self.as_constant(f.expr)))
-                       .collect();
-
-        let fields: Vec<_> =
-            field_names.into_iter()
-                       .map(|n| fields_map[&n].clone())
-                       .collect();
-
-        fields
+                    &format!("expression is not a valid constant {:?}", kind)),
+        }
     }
 }
index 0ceafcc9a62667f1fa152d01c3e41bc7efd04699..d93304f034dd8af87b3c5d15994bf872c753de28 100644 (file)
@@ -15,13 +15,13 @@ use build::expr::category::Category;
 use hair::*;
 use repr::*;
 
-impl<H:Hair> Builder<H> {
+impl<'a,'tcx> Builder<'a,'tcx> {
     /// Compile `expr`, yielding an lvalue that we can move from etc.
     pub fn as_lvalue<M>(&mut self,
                         block: BasicBlock,
                         expr: M)
-                        -> BlockAnd<Lvalue<H>>
-        where M: Mirror<H, Output=Expr<H>>
+                        -> BlockAnd<Lvalue<'tcx>>
+        where M: Mirror<'tcx, Output=Expr<'tcx>>
     {
         let expr = self.hir.mirror(expr);
         self.expr_as_lvalue(block, expr)
@@ -29,22 +29,15 @@ impl<H:Hair> Builder<H> {
 
     fn expr_as_lvalue(&mut self,
                       mut block: BasicBlock,
-                      expr: Expr<H>)
-                      -> BlockAnd<Lvalue<H>>
-    {
-        debug!("expr_as_lvalue(block={:?}, expr={:?})",
-               block, expr);
+                      expr: Expr<'tcx>)
+                      -> BlockAnd<Lvalue<'tcx>> {
+        debug!("expr_as_lvalue(block={:?}, expr={:?})", block, expr);
 
         let this = self;
         let expr_span = expr.span;
         match expr.kind {
             ExprKind::Scope { extent, value } => {
-                this.in_scope(extent, block, |this| {
-                    this.as_lvalue(block, value)
-                })
-            }
-            ExprKind::Paren { arg } => {
-                this.as_lvalue(block, arg)
+                this.in_scope(extent, block, |this| this.as_lvalue(block, value))
             }
             ExprKind::Field { lhs, name } => {
                 let lvalue = unpack!(block = this.as_lvalue(block, lhs));
@@ -72,12 +65,11 @@ impl<H:Hair> Builder<H> {
                                                            idx.clone(),
                                                            Operand::Consume(len)));
 
-                let (success, failure) = (this.cfg.start_new_block(),
-                                          this.cfg.start_new_block());
+                let (success, failure) = (this.cfg.start_new_block(), this.cfg.start_new_block());
                 this.cfg.terminate(block,
                                    Terminator::If {
                                        cond: Operand::Consume(lt),
-                                       targets: [success, failure]
+                                       targets: [success, failure],
                                    });
                 this.panic(failure);
                 success.and(slice.index(idx))
index ee090571b7cc5950dd1a1ff3e03534553a185b68..6b2c487d0f529ec5b3f1bb76d64193afeb7042a3 100644 (file)
@@ -15,16 +15,13 @@ use build::expr::category::Category;
 use hair::*;
 use repr::*;
 
-impl<H:Hair> Builder<H> {
+impl<'a,'tcx> Builder<'a,'tcx> {
     /// Compile `expr` into a value that can be used as an operand.
     /// If `expr` is an lvalue like `x`, this will introduce a
     /// temporary `tmp = x`, so that we capture the value of `x` at
     /// this time.
-    pub fn as_operand<M>(&mut self,
-                         block: BasicBlock,
-                         expr: M)
-                         -> BlockAnd<Operand<H>>
-        where M: Mirror<H, Output=Expr<H>>
+    pub fn as_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>>
+        where M: Mirror<'tcx, Output = Expr<'tcx>>
     {
         let expr = self.hir.mirror(expr);
         self.expr_as_operand(block, expr)
@@ -32,23 +29,13 @@ impl<H:Hair> Builder<H> {
 
     fn expr_as_operand(&mut self,
                        mut block: BasicBlock,
-                       expr: Expr<H>)
-                       -> BlockAnd<Operand<H>>
-    {
-        debug!("expr_as_operand(block={:?}, expr={:?})",
-               block, expr);
+                       expr: Expr<'tcx>)
+                       -> BlockAnd<Operand<'tcx>> {
+        debug!("expr_as_operand(block={:?}, expr={:?})", block, expr);
         let this = self;
 
-        match expr.kind {
-            ExprKind::Scope { extent, value } => {
-                return this.in_scope(extent, block, |this| {
-                    this.as_operand(block, value)
-                });
-            }
-            ExprKind::Paren { arg } => {
-                return this.as_operand(block, arg);
-            }
-            _ => { }
+        if let ExprKind::Scope { extent, value } = expr.kind {
+            return this.in_scope(extent, block, |this| this.as_operand(block, value));
         }
 
         let category = Category::of(&expr.kind).unwrap();
index e4d3ad21503ed0de6b4acce88627aaa8ffb0d7ef..3cfc51ec3c98adda6fafbda78d1caa5c25f3469c 100644 (file)
@@ -17,13 +17,10 @@ use build::expr::category::{Category, RvalueFunc};
 use hair::*;
 use repr::*;
 
-impl<H:Hair> Builder<H> {
+impl<'a,'tcx> Builder<'a,'tcx> {
     /// Compile `expr`, yielding an rvalue.
-    pub fn as_rvalue<M>(&mut self,
-                        block: BasicBlock,
-                        expr: M)
-                        -> BlockAnd<Rvalue<H>>
-        where M: Mirror<H, Output=Expr<H>>
+    pub fn as_rvalue<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Rvalue<'tcx>>
+        where M: Mirror<'tcx, Output = Expr<'tcx>>
     {
         let expr = self.hir.mirror(expr);
         self.expr_as_rvalue(block, expr)
@@ -31,23 +28,16 @@ impl<H:Hair> Builder<H> {
 
     fn expr_as_rvalue(&mut self,
                       mut block: BasicBlock,
-                      expr: Expr<H>)
-                      -> BlockAnd<Rvalue<H>>
-    {
-        debug!("expr_as_rvalue(block={:?}, expr={:?})",
-               block, expr);
+                      expr: Expr<'tcx>)
+                      -> BlockAnd<Rvalue<'tcx>> {
+        debug!("expr_as_rvalue(block={:?}, expr={:?})", block, expr);
 
         let this = self;
         let expr_span = expr.span;
 
         match expr.kind {
             ExprKind::Scope { extent, value } => {
-                this.in_scope(extent, block, |this| {
-                    this.as_rvalue(block, value)
-                })
-            }
-            ExprKind::Paren { arg } => {
-                this.as_rvalue(block, arg)
+                this.in_scope(extent, block, |this| this.as_rvalue(block, value))
             }
             ExprKind::InlineAsm { asm } => {
                 block.and(Rvalue::InlineAsm(asm))
@@ -70,7 +60,7 @@ impl<H:Hair> Builder<H> {
                 let arg = unpack!(block = this.as_operand(block, arg));
                 block.and(Rvalue::UnaryOp(op, arg))
             }
-            ExprKind::Box { place: _, value } => {
+            ExprKind::Box { value } => {
                 let value = this.hir.mirror(value);
                 let value_ty = value.ty.clone();
                 let result = this.temp(value_ty.clone());
@@ -165,11 +155,9 @@ impl<H:Hair> Builder<H> {
                           .map(|f| (f.name, unpack!(block = this.as_operand(block, f.expr))))
                           .collect();
 
-                let field_names =
-                    this.hir.fields(adt_def, variant_index);
+                let field_names = this.hir.fields(adt_def, variant_index);
 
-                let base =
-                    base.map(|base| unpack!(block = this.as_lvalue(block, base)));
+                let base = base.map(|base| unpack!(block = this.as_lvalue(block, base)));
 
                 // for the actual values we use, take either the
                 // expr the user specified or, if they didn't
index 50f04e0177b0bfa50dd82a1a2ab5ac71a8d69960..7c85e9e7174638abbe9e7ec09aea62d8405fe361 100644 (file)
@@ -15,38 +15,22 @@ use build::expr::category::Category;
 use hair::*;
 use repr::*;
 
-impl<H:Hair> Builder<H> {
+impl<'a,'tcx> Builder<'a,'tcx> {
     /// Compile `expr` into a fresh temporary. This is used when building
     /// up rvalues so as to freeze the value that will be consumed.
-    pub fn as_temp<M>(&mut self,
-                      block: BasicBlock,
-                      expr: M)
-                      -> BlockAnd<Lvalue<H>>
-        where M: Mirror<H, Output=Expr<H>>
+    pub fn as_temp<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Lvalue<'tcx>>
+        where M: Mirror<'tcx, Output = Expr<'tcx>>
     {
         let expr = self.hir.mirror(expr);
         self.expr_as_temp(block, expr)
     }
 
-    fn expr_as_temp(&mut self,
-                    mut block: BasicBlock,
-                    expr: Expr<H>)
-                    -> BlockAnd<Lvalue<H>>
-    {
-        debug!("expr_as_temp(block={:?}, expr={:?})",
-               block, expr);
+    fn expr_as_temp(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd<Lvalue<'tcx>> {
+        debug!("expr_as_temp(block={:?}, expr={:?})", block, expr);
         let this = self;
 
-        match expr.kind {
-            ExprKind::Scope { extent, value } => {
-                return this.in_scope(extent, block, |this| {
-                    this.as_temp(block, value)
-                });
-            }
-            ExprKind::Paren { arg } => {
-                return this.as_temp(block, arg);
-            }
-            _ => { }
+        if let ExprKind::Scope { extent, value } = expr.kind {
+            return this.in_scope(extent, block, |this| this.as_temp(block, value));
         }
 
         let expr_ty = expr.ty.clone();
@@ -54,9 +38,7 @@ impl<H:Hair> Builder<H> {
         let temp_lifetime = match expr.temp_lifetime {
             Some(t) => t,
             None => {
-                this.hir.span_bug(
-                    expr.span,
-                    &format!("no temp_lifetime for expr"));
+                this.hir.span_bug(expr.span, &format!("no temp_lifetime for expr"));
             }
         };
         this.schedule_drop(expr.span, temp_lifetime, DropKind::Deep, &temp, expr_ty);
index 1f9928acdc81bf8c1216e1a27ee7f3c6b7dbf2af..658b7779b44a947f1bf8b7be40a983bcc14cff6f 100644 (file)
@@ -41,11 +41,9 @@ pub enum RvalueFunc {
 /// Determines the category for a given expression. Note that scope
 /// and paren expressions have no category.
 impl Category {
-    pub fn of<H:Hair>(ek: &ExprKind<H>) -> Option<Category> {
+    pub fn of<'tcx>(ek: &ExprKind<'tcx>) -> Option<Category> {
         match *ek {
-            ExprKind::Scope { .. } |
-            ExprKind::Paren { .. } =>
-                None,
+            ExprKind::Scope { .. } => None,
 
             ExprKind::Field { .. } |
             ExprKind::Deref { .. } |
index b409903ad7eb51f19a02378f658f903ec899796b..a7d68b09b54592bae360e504f5c96635b56a11cc 100644 (file)
@@ -15,14 +15,16 @@ use build::expr::category::{Category, RvalueFunc};
 use build::scope::LoopScope;
 use hair::*;
 use repr::*;
+use rustc::middle::region::CodeExtent;
+use syntax::codemap::Span;
 
-impl<H:Hair> Builder<H> {
+impl<'a,'tcx> Builder<'a,'tcx> {
     /// Compile `expr`, storing the result into `destination`, which
     /// is assumed to be uninitialized.
     pub fn into_expr(&mut self,
-                     destination: &Lvalue<H>,
+                     destination: &Lvalue<'tcx>,
                      mut block: BasicBlock,
-                     expr: Expr<H>)
+                     expr: Expr<'tcx>)
                      -> BlockAnd<()>
     {
         debug!("into_expr(destination={:?}, block={:?}, expr={:?})",
@@ -36,12 +38,7 @@ impl<H:Hair> Builder<H> {
 
         match expr.kind {
             ExprKind::Scope { extent, value } => {
-                this.in_scope(extent, block, |this| {
-                    this.into(destination, block, value)
-                })
-            }
-            ExprKind::Paren { arg } => {
-                this.into(destination, block, arg)
+                this.in_scope(extent, block, |this| this.into(destination, block, value))
             }
             ExprKind::Block { body: ast_block } => {
                 this.ast_block(destination, block, ast_block)
@@ -102,14 +99,16 @@ impl<H:Hair> Builder<H> {
                     true_block, expr_span, destination,
                     Constant {
                         span: expr_span,
-                        kind: ConstantKind::Literal(Literal::Bool { value: true }),
+                        ty: this.hir.bool_ty(),
+                        literal: this.hir.true_literal(),
                     });
 
                 this.cfg.push_assign_constant(
                     false_block, expr_span, destination,
                     Constant {
                         span: expr_span,
-                        kind: ConstantKind::Literal(Literal::Bool { value: false }),
+                        ty: this.hir.bool_ty(),
+                        literal: this.hir.false_literal(),
                     });
 
                 this.cfg.terminate(true_block, Terminator::Goto { target: join_block });
@@ -203,8 +202,7 @@ impl<H:Hair> Builder<H> {
                                        |loop_scope| loop_scope.continue_block)
             }
             ExprKind::Break { label } => {
-                this.break_or_continue(expr_span, label, block,
-                                       |loop_scope| loop_scope.break_block)
+                this.break_or_continue(expr_span, label, block, |loop_scope| loop_scope.break_block)
             }
             ExprKind::Return { value } => {
                 unpack!(block = this.into(&Lvalue::ReturnPointer, block, value));
@@ -225,9 +223,9 @@ impl<H:Hair> Builder<H> {
                                        data: CallData {
                                            destination: destination.clone(),
                                            func: fun,
-                                           args: args
+                                           args: args,
                                        },
-                                       targets: [success, panic]
+                                       targets: [success, panic],
                                    });
                 success.unit()
             }
@@ -267,12 +265,12 @@ impl<H:Hair> Builder<H> {
     }
 
     fn break_or_continue<F>(&mut self,
-                            span: H::Span,
-                            label: Option<H::CodeExtent>,
+                            span: Span,
+                            label: Option<CodeExtent>,
                             block: BasicBlock,
                             exit_selector: F)
                             -> BlockAnd<()>
-        where F: FnOnce(&LoopScope<H>) -> BasicBlock
+        where F: FnOnce(&LoopScope) -> BasicBlock
     {
         let loop_scope = self.find_loop_scope(span, label);
         let exit_block = exit_selector(&loop_scope);
index 426e59f1c401c912170c62c38b569d7c2407731b..c6f1b777d663e4a0aa0eade8e24b6686113c4ee7 100644 (file)
@@ -18,53 +18,56 @@ use build::{BlockAnd, Builder};
 use hair::*;
 use repr::*;
 
-pub trait EvalInto<H:Hair> {
-    fn eval_into(self, builder: &mut Builder<H>, destination: &Lvalue<H>,
-                 block: BasicBlock) -> BlockAnd<()>;
+pub trait EvalInto<'tcx> {
+    fn eval_into<'a>(self,
+                     builder: &mut Builder<'a, 'tcx>,
+                     destination: &Lvalue<'tcx>,
+                     block: BasicBlock)
+                     -> BlockAnd<()>;
 }
 
-impl<H:Hair> Builder<H> {
+impl<'a,'tcx> Builder<'a,'tcx> {
     pub fn into<E>(&mut self,
-                   destination: &Lvalue<H>,
+                   destination: &Lvalue<'tcx>,
                    block: BasicBlock,
                    expr: E)
                    -> BlockAnd<()>
-        where E: EvalInto<H>
+        where E: EvalInto<'tcx>
     {
         expr.eval_into(self, destination, block)
     }
 }
 
-impl<H:Hair> EvalInto<H> for ExprRef<H> {
-    fn eval_into(self,
-                 builder: &mut Builder<H>,
-                 destination: &Lvalue<H>,
-                 block: BasicBlock)
-                 -> BlockAnd<()> {
+impl<'tcx> EvalInto<'tcx> for ExprRef<'tcx> {
+    fn eval_into<'a>(self,
+                     builder: &mut Builder<'a, 'tcx>,
+                     destination: &Lvalue<'tcx>,
+                     block: BasicBlock)
+                     -> BlockAnd<()> {
         let expr = builder.hir.mirror(self);
         builder.into_expr(destination, block, expr)
     }
 }
 
-impl<H:Hair> EvalInto<H> for Expr<H> {
-    fn eval_into(self,
-                 builder: &mut Builder<H>,
-                 destination: &Lvalue<H>,
-                 block: BasicBlock)
-                 -> BlockAnd<()> {
+impl<'tcx> EvalInto<'tcx> for Expr<'tcx> {
+    fn eval_into<'a>(self,
+                     builder: &mut Builder<'a, 'tcx>,
+                     destination: &Lvalue<'tcx>,
+                     block: BasicBlock)
+                     -> BlockAnd<()> {
         builder.into_expr(destination, block, self)
     }
 }
 
-impl<H:Hair> EvalInto<H> for Option<ExprRef<H>> {
-    fn eval_into(self,
-                 builder: &mut Builder<H>,
-                 destination: &Lvalue<H>,
-                 block: BasicBlock)
-                 -> BlockAnd<()> {
+impl<'tcx> EvalInto<'tcx> for Option<ExprRef<'tcx>> {
+    fn eval_into<'a>(self,
+                     builder: &mut Builder<'a, 'tcx>,
+                     destination: &Lvalue<'tcx>,
+                     block: BasicBlock)
+                     -> BlockAnd<()> {
         match self {
             Some(expr) => builder.into(destination, block, expr),
-            None => block.unit()
+            None => block.unit(),
         }
     }
 }
index 7f0b3ee3b316bb13a13e4cd1d57cb0f83a2cae6f..6e0b05d5dea79304dca828432f32f26219f6dfe2 100644 (file)
 
 use build::{BlockAnd, Builder};
 use repr::*;
+use rustc::middle::region::CodeExtent;
+use rustc::middle::ty::{AdtDef, Ty};
 use hair::*;
+use syntax::ast::{Name, NodeId};
+use syntax::codemap::Span;
 
 // helper functions, broken out by category:
 mod simplify;
 mod test;
 mod util;
 
-impl<H:Hair> Builder<H> {
+impl<'a,'tcx> Builder<'a,'tcx> {
     pub fn match_expr(&mut self,
-                      destination: &Lvalue<H>,
-                      span: H::Span,
+                      destination: &Lvalue<'tcx>,
+                      span: Span,
                       mut block: BasicBlock,
-                      discriminant: ExprRef<H>,
-                      arms: Vec<Arm<H>>)
-                      -> BlockAnd<()>
-    {
-        let discriminant_lvalue =
-            unpack!(block = self.as_lvalue(block, discriminant));
+                      discriminant: ExprRef<'tcx>,
+                      arms: Vec<Arm<'tcx>>)
+                      -> BlockAnd<()> {
+        let discriminant_lvalue = unpack!(block = self.as_lvalue(block, discriminant));
+
+        // Before we do anything, create uninitialized variables with
+        // suitable extent for all of the bindings in this match. It's
+        // easiest to do this up front because some of these arms may
+        // be unreachable or reachable multiple times.
+        let var_extent = self.extent_of_innermost_scope().unwrap();
+        for arm in &arms {
+            self.declare_bindings(var_extent, arm.patterns[0].clone());
+        }
 
-        let arm_blocks: Vec<BasicBlock> =
-            arms.iter()
-                .map(|_| self.cfg.start_new_block())
-                .collect();
+        let mut arm_blocks = ArmBlocks {
+            blocks: arms.iter()
+                        .map(|_| self.cfg.start_new_block())
+                        .collect(),
+        };
 
-        let arm_bodies: Vec<ExprRef<H>> =
+        let arm_bodies: Vec<ExprRef<'tcx>> =
             arms.iter()
                 .map(|arm| arm.body.clone())
                 .collect();
@@ -50,36 +62,34 @@ impl<H:Hair> Builder<H> {
         // highest priority candidate comes last in the list. This the
         // reverse of the order in which candidates are written in the
         // source.
-        let candidates: Vec<Candidate<H>> =
-            arms.into_iter()
-                .zip(arm_blocks.iter())
+        let candidates: Vec<Candidate<'tcx>> =
+            arms.iter()
+                .enumerate()
                 .rev() // highest priority comes last
-                .flat_map(|(arm, &arm_block)| {
-                    let guard = arm.guard;
-                    arm.patterns.into_iter()
+                .flat_map(|(arm_index, arm)| {
+                    arm.patterns.iter()
                                 .rev()
-                                .map(move |pat| (arm_block, pat, guard.clone()))
+                                .map(move |pat| (arm_index, pat.clone(), arm.guard.clone()))
                 })
-                .map(|(arm_block, pattern, guard)| {
+                .map(|(arm_index, pattern, guard)| {
                     Candidate {
                         match_pairs: vec![self.match_pair(discriminant_lvalue.clone(), pattern)],
                         bindings: vec![],
                         guard: guard,
-                        arm_block: arm_block,
+                        arm_index: arm_index,
                     }
                 })
                 .collect();
 
         // this will generate code to test discriminant_lvalue and
         // branch to the appropriate arm block
-        let var_extent = self.extent_of_innermost_scope().unwrap();
-        self.match_candidates(span, var_extent, candidates, block);
+        self.match_candidates(span, &mut arm_blocks, candidates, block);
 
         // all the arm blocks will rejoin here
         let end_block = self.cfg.start_new_block();
 
-        for (arm_body, &arm_block) in arm_bodies.into_iter().zip(arm_blocks.iter()) {
-            let mut arm_block = arm_block;
+        for (arm_index, arm_body) in arm_bodies.into_iter().enumerate() {
+            let mut arm_block = arm_blocks.blocks[arm_index];
             unpack!(arm_block = self.into(destination, arm_block, arm_body));
             self.cfg.terminate(arm_block, Terminator::Goto { target: end_block });
         }
@@ -89,11 +99,10 @@ impl<H:Hair> Builder<H> {
 
     pub fn expr_into_pattern(&mut self,
                              mut block: BasicBlock,
-                             var_extent: H::CodeExtent,          // lifetime of vars
-                             irrefutable_pat: PatternRef<H>,
-                             initializer: ExprRef<H>)
-                             -> BlockAnd<()>
-    {
+                             var_extent: CodeExtent, // lifetime of vars
+                             irrefutable_pat: PatternRef<'tcx>,
+                             initializer: ExprRef<'tcx>)
+                             -> BlockAnd<()> {
         // optimize the case of `let x = ...`
         let irrefutable_pat = self.hir.mirror(irrefutable_pat);
         match irrefutable_pat.kind {
@@ -103,31 +112,39 @@ impl<H:Hair> Builder<H> {
                                    var,
                                    ty,
                                    subpattern: None } => {
-                let index = self.declare_binding(var_extent, mutability, name,
-                                                 var, ty, irrefutable_pat.span);
+                let index = self.declare_binding(var_extent,
+                                                 mutability,
+                                                 name,
+                                                 var,
+                                                 ty,
+                                                 irrefutable_pat.span);
                 let lvalue = Lvalue::Var(index);
                 return self.into(&lvalue, block, initializer);
             }
-            _ => { }
+            _ => {}
         }
         let lvalue = unpack!(block = self.as_lvalue(block, initializer));
-        self.lvalue_into_pattern(block, var_extent,
-                                 PatternRef::Mirror(Box::new(irrefutable_pat)), &lvalue)
+        self.lvalue_into_pattern(block,
+                                 var_extent,
+                                 PatternRef::Mirror(Box::new(irrefutable_pat)),
+                                 &lvalue)
     }
 
     pub fn lvalue_into_pattern(&mut self,
                                mut block: BasicBlock,
-                               var_extent: H::CodeExtent,
-                               irrefutable_pat: PatternRef<H>,
-                               initializer: &Lvalue<H>)
-                               -> BlockAnd<()>
-    {
+                               var_extent: CodeExtent,
+                               irrefutable_pat: PatternRef<'tcx>,
+                               initializer: &Lvalue<'tcx>)
+                               -> BlockAnd<()> {
+        // first, creating the bindings
+        self.declare_bindings(var_extent, irrefutable_pat.clone());
+
         // create a dummy candidate
-        let mut candidate = Candidate::<H> {
-            match_pairs: vec![self.match_pair(initializer.clone(), irrefutable_pat)],
+        let mut candidate = Candidate::<'tcx> {
+            match_pairs: vec![self.match_pair(initializer.clone(), irrefutable_pat.clone())],
             bindings: vec![],
             guard: None,
-            arm_block: block
+            arm_index: 0, // since we don't call `match_candidates`, this field is unused
         };
 
         // Simplify the candidate. Since the pattern is irrefutable, this should
@@ -135,119 +152,133 @@ impl<H:Hair> Builder<H> {
         unpack!(block = self.simplify_candidate(block, &mut candidate));
 
         if !candidate.match_pairs.is_empty() {
-            self.hir.span_bug(
-                candidate.match_pairs[0].pattern.span,
-                &format!("match pairs {:?} remaining after simplifying irrefutable pattern",
-                         candidate.match_pairs));
+            self.hir.span_bug(candidate.match_pairs[0].pattern.span,
+                              &format!("match pairs {:?} remaining after simplifying \
+                                        irrefutable pattern",
+                                       candidate.match_pairs));
         }
 
         // now apply the bindings, which will also declare the variables
-        self.bind_matched_candidate(block, var_extent, candidate.bindings);
+        self.bind_matched_candidate(block, candidate.bindings);
 
         block.unit()
     }
 
-    pub fn declare_uninitialized_variables(&mut self,
-                                           var_extent: H::CodeExtent,
-                                           pattern: PatternRef<H>)
-    {
+    pub fn declare_bindings(&mut self, var_extent: CodeExtent, pattern: PatternRef<'tcx>) {
         let pattern = self.hir.mirror(pattern);
         match pattern.kind {
             PatternKind::Binding { mutability, name, mode: _, var, ty, subpattern } => {
                 self.declare_binding(var_extent, mutability, name, var, ty, pattern.span);
                 if let Some(subpattern) = subpattern {
-                    self.declare_uninitialized_variables(var_extent, subpattern);
+                    self.declare_bindings(var_extent, subpattern);
                 }
             }
             PatternKind::Array { prefix, slice, suffix } |
             PatternKind::Slice { prefix, slice, suffix } => {
                 for subpattern in prefix.into_iter().chain(slice).chain(suffix) {
-                    self.declare_uninitialized_variables(var_extent, subpattern);
+                    self.declare_bindings(var_extent, subpattern);
                 }
             }
-            PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {
-            }
+            PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {}
             PatternKind::Deref { subpattern } => {
-                self.declare_uninitialized_variables(var_extent, subpattern);
+                self.declare_bindings(var_extent, subpattern);
             }
             PatternKind::Leaf { subpatterns } |
             PatternKind::Variant { subpatterns, .. } => {
                 for subpattern in subpatterns {
-                    self.declare_uninitialized_variables(var_extent, subpattern.pattern);
+                    self.declare_bindings(var_extent, subpattern.pattern);
                 }
             }
         }
     }
 }
 
+/// List of blocks for each arm (and potentially other metadata in the
+/// future).
+struct ArmBlocks {
+    blocks: Vec<BasicBlock>,
+}
+
 #[derive(Clone, Debug)]
-struct Candidate<H:Hair> {
+struct Candidate<'tcx> {
     // all of these must be satisfied...
-    match_pairs: Vec<MatchPair<H>>,
+    match_pairs: Vec<MatchPair<'tcx>>,
 
     // ...these bindings established...
-    bindings: Vec<Binding<H>>,
+    bindings: Vec<Binding<'tcx>>,
 
     // ...and the guard must be evaluated...
-    guard: Option<ExprRef<H>>,
+    guard: Option<ExprRef<'tcx>>,
 
-    // ...and then we branch here.
-    arm_block: BasicBlock,
+    // ...and then we branch to arm with this index.
+    arm_index: usize,
 }
 
 #[derive(Clone, Debug)]
-struct Binding<H:Hair> {
-    span: H::Span,
-    source: Lvalue<H>,
-    name: H::Ident,
-    var_id: H::VarId,
-    var_ty: H::Ty,
+struct Binding<'tcx> {
+    span: Span,
+    source: Lvalue<'tcx>,
+    name: Name,
+    var_id: NodeId,
+    var_ty: Ty<'tcx>,
     mutability: Mutability,
-    binding_mode: BindingMode<H>,
+    binding_mode: BindingMode,
 }
 
 #[derive(Clone, Debug)]
-struct MatchPair<H:Hair> {
+struct MatchPair<'tcx> {
     // this lvalue...
-    lvalue: Lvalue<H>,
+    lvalue: Lvalue<'tcx>,
 
     // ... must match this pattern.
-    pattern: Pattern<H>,
+    pattern: Pattern<'tcx>,
 }
 
 #[derive(Clone, Debug, PartialEq)]
-enum TestKind<H:Hair> {
+enum TestKind<'tcx> {
     // test the branches of enum
-    Switch { adt_def: H::AdtDef },
+    Switch {
+        adt_def: AdtDef<'tcx>,
+    },
 
     // test for equality
-    Eq { value: Constant<H>, ty: H::Ty },
+    Eq {
+        value: Literal<'tcx>,
+        ty: Ty<'tcx>,
+    },
 
     // test whether the value falls within an inclusive range
-    Range { lo: Constant<H>, hi: Constant<H>, ty: H::Ty },
+    Range {
+        lo: Literal<'tcx>,
+        hi: Literal<'tcx>,
+        ty: Ty<'tcx>,
+    },
 
     // test length of the slice is equal to len
-    Len { len: usize, op: BinOp },
+    Len {
+        len: usize,
+        op: BinOp,
+    },
 }
 
 #[derive(Debug)]
-struct Test<H:Hair> {
-    span: H::Span,
-    kind: TestKind<H>,
+struct Test<'tcx> {
+    span: Span,
+    kind: TestKind<'tcx>,
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // Main matching algorithm
 
-impl<H:Hair> Builder<H> {
+impl<'a,'tcx> Builder<'a,'tcx> {
     fn match_candidates(&mut self,
-                        span: H::Span,
-                        var_extent: H::CodeExtent,
-                        mut candidates: Vec<Candidate<H>>,
+                        span: Span,
+                        arm_blocks: &mut ArmBlocks,
+                        mut candidates: Vec<Candidate<'tcx>>,
                         mut block: BasicBlock)
     {
-        debug!("matched_candidate(span={:?}, var_extent={:?}, block={:?}, candidates={:?})",
-               span, var_extent, block, candidates);
+        debug!("matched_candidate(span={:?}, block={:?}, candidates={:?})",
+               span, block, candidates);
 
         // Start by simplifying candidates. Once this process is
         // complete, all the match pairs which remain require some
@@ -267,9 +298,12 @@ impl<H:Hair> Builder<H> {
             // If so, apply any bindings, test the guard (if any), and
             // branch to the arm.
             let candidate = candidates.pop().unwrap();
-            match self.bind_and_guard_matched_candidate(block, var_extent, candidate) {
-                None => { return; }
-                Some(b) => { block = b; }
+            if let Some(b) = self.bind_and_guard_matched_candidate(block, arm_blocks, candidate) {
+                block = b;
+            } else {
+                // if None is returned, then any remaining candidates
+                // are unreachable (at least not through this path).
+                return;
             }
         }
 
@@ -286,7 +320,7 @@ impl<H:Hair> Builder<H> {
         let target_blocks = self.perform_test(block, &match_pair.lvalue, &test);
 
         for (outcome, mut target_block) in target_blocks.into_iter().enumerate() {
-            let applicable_candidates: Vec<Candidate<H>> =
+            let applicable_candidates: Vec<Candidate<'tcx>> =
                 candidates.iter()
                           .filter_map(|candidate| {
                               unpack!(target_block =
@@ -297,7 +331,7 @@ impl<H:Hair> Builder<H> {
                                                                       candidate))
                           })
                           .collect();
-            self.match_candidates(span, var_extent, applicable_candidates, target_block);
+            self.match_candidates(span, arm_blocks, applicable_candidates, target_block);
         }
     }
 
@@ -315,15 +349,17 @@ impl<H:Hair> Builder<H> {
     /// MIR).
     fn bind_and_guard_matched_candidate(&mut self,
                                         mut block: BasicBlock,
-                                        var_extent: H::CodeExtent,
-                                        candidate: Candidate<H>)
+                                        arm_blocks: &mut ArmBlocks,
+                                        candidate: Candidate<'tcx>)
                                         -> Option<BasicBlock> {
-        debug!("bind_and_guard_matched_candidate(block={:?}, var_extent={:?}, candidate={:?})",
-               block, var_extent, candidate);
+        debug!("bind_and_guard_matched_candidate(block={:?}, candidate={:?})",
+               block, candidate);
 
         debug_assert!(candidate.match_pairs.is_empty());
 
-        self.bind_matched_candidate(block, var_extent, candidate.bindings);
+        self.bind_matched_candidate(block, candidate.bindings);
+
+        let arm_block = arm_blocks.blocks[candidate.arm_index];
 
         if let Some(guard) = candidate.guard {
             // the block to branch to if the guard fails; if there is no
@@ -331,36 +367,26 @@ impl<H:Hair> Builder<H> {
             let cond = unpack!(block = self.as_operand(block, guard));
             let otherwise = self.cfg.start_new_block();
             self.cfg.terminate(block, Terminator::If { cond: cond,
-                                                       targets: [candidate.arm_block, otherwise]});
+                                                       targets: [arm_block, otherwise]});
             Some(otherwise)
         } else {
-            self.cfg.terminate(block, Terminator::Goto { target: candidate.arm_block });
+            self.cfg.terminate(block, Terminator::Goto { target: arm_block });
             None
         }
     }
 
     fn bind_matched_candidate(&mut self,
                               block: BasicBlock,
-                              var_extent: H::CodeExtent,
-                              bindings: Vec<Binding<H>>) {
-        debug!("bind_matched_candidate(block={:?}, var_extent={:?}, bindings={:?})",
-               block, var_extent, bindings);
+                              bindings: Vec<Binding<'tcx>>) {
+        debug!("bind_matched_candidate(block={:?}, bindings={:?})",
+               block, bindings);
 
         // Assign each of the bindings. This may trigger moves out of the candidate.
         for binding in bindings {
-            // Create a variable for the `var_id` being bound. In the
-            // case where there are multiple patterns for a single
-            // arm, it may already exist.
-            let var_index = if !self.var_indices.contains_key(&binding.var_id) {
-                self.declare_binding(var_extent,
-                                     binding.mutability,
-                                     binding.name,
-                                     binding.var_id,
-                                     binding.var_ty,
-                                     binding.span)
-            } else {
-                self.var_indices[&binding.var_id]
-            };
+            // Find the variable for the `var_id` being bound. It
+            // should have been created by a previous call to
+            // `declare_bindings`.
+            let var_index = self.var_indices[&binding.var_id];
 
             let rvalue = match binding.binding_mode {
                 BindingMode::ByValue =>
@@ -374,19 +400,19 @@ impl<H:Hair> Builder<H> {
     }
 
     fn declare_binding(&mut self,
-                       var_extent: H::CodeExtent,
+                       var_extent: CodeExtent,
                        mutability: Mutability,
-                       name: H::Ident,
-                       var_id: H::VarId,
-                       var_ty: H::Ty,
-                       span: H::Span)
+                       name: Name,
+                       var_id: NodeId,
+                       var_ty: Ty<'tcx>,
+                       span: Span)
                        -> u32
     {
         debug!("declare_binding(var_id={:?}, name={:?}, var_ty={:?}, var_extent={:?}, span={:?})",
                var_id, name, var_ty, var_extent, span);
 
         let index = self.var_decls.len();
-        self.var_decls.push(VarDecl::<H> {
+        self.var_decls.push(VarDecl::<'tcx> {
             mutability: mutability,
             name: name,
             ty: var_ty.clone(),
@@ -400,4 +426,3 @@ impl<H:Hair> Builder<H> {
         index
     }
 }
-
index f15b2ed5d4e59a57c423179fb28d577a549aada2..0267e9b10ceccb13740ac6381bb61abce540af95 100644 (file)
@@ -29,19 +29,20 @@ use repr::*;
 
 use std::mem;
 
-impl<H:Hair> Builder<H> {
+impl<'a,'tcx> Builder<'a,'tcx> {
     pub fn simplify_candidate(&mut self,
                               mut block: BasicBlock,
-                              candidate: &mut Candidate<H>)
-                              -> BlockAnd<()>
-    {
+                              candidate: &mut Candidate<'tcx>)
+                              -> BlockAnd<()> {
         // repeatedly simplify match pairs until fixed point is reached
         loop {
             let match_pairs = mem::replace(&mut candidate.match_pairs, vec![]);
             let mut progress = match_pairs.len(); // count how many were simplified
             for match_pair in match_pairs {
                 match self.simplify_match_pair(block, match_pair, candidate) {
-                    Ok(b) => { block = b; }
+                    Ok(b) => {
+                        block = b;
+                    }
                     Err(match_pair) => {
                         candidate.match_pairs.push(match_pair);
                         progress -= 1; // this one was not simplified
@@ -56,14 +57,14 @@ impl<H:Hair> Builder<H> {
 
     /// Tries to simplify `match_pair`, returning true if
     /// successful. If successful, new match pairs and bindings will
-    /// have been pushed into the candidate. On failure (if false is
-    /// returned), no changes are made to candidate.
+    /// have been pushed into the candidate. If no simplification is
+    /// possible, Err is returned and no changes are made to
+    /// candidate.
     fn simplify_match_pair(&mut self,
                            mut block: BasicBlock,
-                           match_pair: MatchPair<H>,
-                           candidate: &mut Candidate<H>)
-                           -> Result<BasicBlock, MatchPair<H>> // returns Err() if cannot simplify
-    {
+                           match_pair: MatchPair<'tcx>,
+                           candidate: &mut Candidate<'tcx>)
+                           -> Result<BasicBlock, MatchPair<'tcx>> {
         match match_pair.pattern.kind {
             PatternKind::Wild(..) => {
                 // nothing left to do
@@ -114,8 +115,8 @@ impl<H:Hair> Builder<H> {
 
             PatternKind::Leaf { subpatterns } => {
                 // tuple struct, match subpats (if any)
-                candidate.match_pairs.extend(
-                    self.field_match_pairs(match_pair.lvalue, subpatterns));
+                candidate.match_pairs
+                         .extend(self.field_match_pairs(match_pair.lvalue, subpatterns));
                 Ok(block)
             }
 
@@ -128,4 +129,3 @@ impl<H:Hair> Builder<H> {
         }
     }
 }
-
index 2d0a6e61beb2819954f8aa1e5f572611cce7633b..d5745eb28c7a845aface6eb6bd2f943261f3fa42 100644 (file)
@@ -19,12 +19,13 @@ use build::{BlockAnd, Builder};
 use build::matches::{Candidate, MatchPair, Test, TestKind};
 use hair::*;
 use repr::*;
+use syntax::codemap::Span;
 
-impl<H:Hair> Builder<H> {
+impl<'a,'tcx> Builder<'a,'tcx> {
     /// Identifies what test is needed to decide if `match_pair` is applicable.
     ///
     /// It is a bug to call this with a simplifyable pattern.
-    pub fn test(&mut self, match_pair: &MatchPair<H>) -> Test<H> {
+    pub fn test(&mut self, match_pair: &MatchPair<'tcx>) -> Test<'tcx> {
         match match_pair.pattern.kind {
             PatternKind::Variant { ref adt_def, variant_index: _, subpatterns: _ } => {
                 Test {
@@ -33,26 +34,34 @@ impl<H:Hair> Builder<H> {
                 }
             }
 
-            PatternKind::Constant { ref expr } => {
-                let expr = self.as_constant(expr.clone());
+            PatternKind::Constant { ref value } => {
                 Test {
                     span: match_pair.pattern.span,
-                    kind: TestKind::Eq { value: expr, ty: match_pair.pattern.ty.clone() },
+                    kind: TestKind::Eq {
+                        value: value.clone(),
+                        ty: match_pair.pattern.ty.clone(),
+                    },
                 }
             }
 
             PatternKind::Range { ref lo, ref hi } => {
-                let lo = self.as_constant(lo.clone());
-                let hi = self.as_constant(hi.clone());
                 Test {
                     span: match_pair.pattern.span,
-                    kind: TestKind::Range { lo: lo, hi: hi, ty: match_pair.pattern.ty.clone() },
+                    kind: TestKind::Range {
+                        lo: lo.clone(),
+                        hi: hi.clone(),
+                        ty: match_pair.pattern.ty.clone(),
+                    },
                 }
             }
 
             PatternKind::Slice { ref prefix, ref slice, ref suffix } => {
                 let len = prefix.len() + suffix.len();
-                let op = if slice.is_some() {BinOp::Ge} else {BinOp::Eq};
+                let op = if slice.is_some() {
+                    BinOp::Ge
+                } else {
+                    BinOp::Eq
+                };
                 Test {
                     span: match_pair.pattern.span,
                     kind: TestKind::Len { len: len, op: op },
@@ -72,8 +81,8 @@ impl<H:Hair> Builder<H> {
     /// Generates the code to perform a test.
     pub fn perform_test(&mut self,
                         block: BasicBlock,
-                        lvalue: &Lvalue<H>,
-                        test: &Test<H>)
+                        lvalue: &Lvalue<'tcx>,
+                        test: &Test<'tcx>)
                         -> Vec<BasicBlock> {
         match test.kind.clone() {
             TestKind::Switch { adt_def } => {
@@ -90,22 +99,28 @@ impl<H:Hair> Builder<H> {
 
             TestKind::Eq { value, ty } => {
                 // call PartialEq::eq(discrim, constant)
-                let constant = self.push_constant(block, test.span, ty.clone(), value);
+                let constant = self.push_literal(block, test.span, ty.clone(), value);
                 let item_ref = self.hir.partial_eq(ty);
                 self.call_comparison_fn(block, test.span, item_ref, lvalue.clone(), constant)
             }
 
             TestKind::Range { lo, hi, ty } => {
                 // Test `v` by computing `PartialOrd::le(lo, v) && PartialOrd::le(v, hi)`.
-                let lo = self.push_constant(block, test.span, ty.clone(), lo);
-                let hi = self.push_constant(block, test.span, ty.clone(), hi);
+                let lo = self.push_literal(block, test.span, ty.clone(), lo);
+                let hi = self.push_literal(block, test.span, ty.clone(), hi);
                 let item_ref = self.hir.partial_le(ty);
 
-                let lo_blocks =
-                    self.call_comparison_fn(block, test.span, item_ref.clone(), lo, lvalue.clone());
+                let lo_blocks = self.call_comparison_fn(block,
+                                                        test.span,
+                                                        item_ref.clone(),
+                                                        lo,
+                                                        lvalue.clone());
 
-                let hi_blocks =
-                    self.call_comparison_fn(lo_blocks[0], test.span, item_ref, lvalue.clone(), hi);
+                let hi_blocks = self.call_comparison_fn(lo_blocks[0],
+                                                        test.span,
+                                                        item_ref,
+                                                        lvalue.clone(),
+                                                        hi);
 
                 let failure = self.cfg.start_new_block();
                 self.cfg.terminate(lo_blocks[1], Terminator::Goto { target: failure });
@@ -119,20 +134,18 @@ impl<H:Hair> Builder<H> {
                 let (actual, result) = (self.temp(usize_ty), self.temp(bool_ty));
 
                 // actual = len(lvalue)
-                self.cfg.push_assign(
-                    block, test.span,
-                    &actual, Rvalue::Len(lvalue.clone()));
+                self.cfg.push_assign(block, test.span, &actual, Rvalue::Len(lvalue.clone()));
 
                 // expected = <N>
-                let expected =
-                    self.push_usize(block, test.span, len);
+                let expected = self.push_usize(block, test.span, len);
 
                 // result = actual == expected OR result = actual < expected
-                self.cfg.push_assign(
-                    block, test.span,
-                    &result, Rvalue::BinaryOp(op,
-                                              Operand::Consume(actual),
-                                              Operand::Consume(expected)));
+                self.cfg.push_assign(block,
+                                     test.span,
+                                     &result,
+                                     Rvalue::BinaryOp(op,
+                                                      Operand::Consume(actual),
+                                                      Operand::Consume(expected)));
 
                 // branch based on result
                 let target_blocks: Vec<_> = vec![self.cfg.start_new_block(),
@@ -149,13 +162,12 @@ impl<H:Hair> Builder<H> {
 
     fn call_comparison_fn(&mut self,
                           block: BasicBlock,
-                          span: H::Span,
-                          item_ref: ItemRef<H>,
-                          lvalue1: Lvalue<H>,
-                          lvalue2: Lvalue<H>)
+                          span: Span,
+                          item_ref: ItemRef<'tcx>,
+                          lvalue1: Lvalue<'tcx>,
+                          lvalue2: Lvalue<'tcx>)
                           -> Vec<BasicBlock> {
-        let target_blocks = vec![self.cfg.start_new_block(),
-                                 self.cfg.start_new_block()];
+        let target_blocks = vec![self.cfg.start_new_block(), self.cfg.start_new_block()];
 
         let bool_ty = self.hir.bool_ty();
         let eq_result = self.temp(bool_ty);
@@ -175,7 +187,7 @@ impl<H:Hair> Builder<H> {
         self.cfg.terminate(call_blocks[0],
                            Terminator::If {
                                cond: Operand::Consume(eq_result),
-                               targets: [target_blocks[0], target_blocks[1]]
+                               targets: [target_blocks[0], target_blocks[1]],
                            });
 
         target_blocks
@@ -194,11 +206,11 @@ impl<H:Hair> Builder<H> {
     /// @ 22])`.
     pub fn candidate_under_assumption(&mut self,
                                       mut block: BasicBlock,
-                                      test_lvalue: &Lvalue<H>,
-                                      test_kind: &TestKind<H>,
+                                      test_lvalue: &Lvalue<'tcx>,
+                                      test_kind: &TestKind<'tcx>,
                                       test_outcome: usize,
-                                      candidate: &Candidate<H>)
-                                      -> BlockAnd<Option<Candidate<H>>> {
+                                      candidate: &Candidate<'tcx>)
+                                      -> BlockAnd<Option<Candidate<'tcx>>> {
         let candidate = candidate.clone();
         let match_pairs = candidate.match_pairs;
         let result = unpack!(block = self.match_pairs_under_assumption(block,
@@ -208,7 +220,7 @@ impl<H:Hair> Builder<H> {
                                                                        match_pairs));
         block.and(match result {
             Some(match_pairs) => Some(Candidate { match_pairs: match_pairs, ..candidate }),
-            None => None
+            None => None,
         })
     }
 
@@ -216,11 +228,11 @@ impl<H:Hair> Builder<H> {
     /// work of transforming the list of match pairs.
     fn match_pairs_under_assumption(&mut self,
                                     mut block: BasicBlock,
-                                    test_lvalue: &Lvalue<H>,
-                                    test_kind: &TestKind<H>,
+                                    test_lvalue: &Lvalue<'tcx>,
+                                    test_kind: &TestKind<'tcx>,
                                     test_outcome: usize,
-                                    match_pairs: Vec<MatchPair<H>>)
-                                    -> BlockAnd<Option<Vec<MatchPair<H>>>> {
+                                    match_pairs: Vec<MatchPair<'tcx>>)
+                                    -> BlockAnd<Option<Vec<MatchPair<'tcx>>>> {
         let mut result = vec![];
 
         for match_pair in match_pairs {
@@ -279,9 +291,9 @@ impl<H:Hair> Builder<H> {
     /// It is a bug to call this with a simplifyable pattern.
     pub fn consequent_match_pairs_under_assumption(&mut self,
                                                    mut block: BasicBlock,
-                                                   match_pair: MatchPair<H>,
+                                                   match_pair: MatchPair<'tcx>,
                                                    test_outcome: usize)
-                                                   -> BlockAnd<Option<Vec<MatchPair<H>>>> {
+                                                   -> BlockAnd<Option<Vec<MatchPair<'tcx>>>> {
         match match_pair.pattern.kind {
             PatternKind::Variant { adt_def, variant_index, subpatterns } => {
                 if test_outcome != variant_index {
@@ -339,9 +351,8 @@ impl<H:Hair> Builder<H> {
         }
     }
 
-    fn error_simplifyable(&mut self, match_pair: &MatchPair<H>) -> ! {
-        self.hir.span_bug(
-            match_pair.pattern.span,
-            &format!("simplifyable pattern found: {:?}", match_pair.pattern))
+    fn error_simplifyable(&mut self, match_pair: &MatchPair<'tcx>) -> ! {
+        self.hir.span_bug(match_pair.pattern.span,
+                          &format!("simplifyable pattern found: {:?}", match_pair.pattern))
     }
 }
index 65a08868666352ad48ee5bfc1fc4380d973575e0..28925f9b38b4f3d28475bcf06f7380eb22854dd6 100644 (file)
@@ -14,11 +14,11 @@ use hair::*;
 use repr::*;
 use std::u32;
 
-impl<H:Hair> Builder<H> {
+impl<'a,'tcx> Builder<'a,'tcx> {
     pub fn field_match_pairs(&mut self,
-                             lvalue: Lvalue<H>,
-                             subpatterns: Vec<FieldPatternRef<H>>)
-                             -> Vec<MatchPair<H>> {
+                             lvalue: Lvalue<'tcx>,
+                             subpatterns: Vec<FieldPatternRef<'tcx>>)
+                             -> Vec<MatchPair<'tcx>> {
         subpatterns.into_iter()
                    .map(|fieldpat| {
                        let lvalue = lvalue.clone().field(fieldpat.field);
@@ -27,7 +27,10 @@ impl<H:Hair> Builder<H> {
                    .collect()
     }
 
-    pub fn match_pair(&mut self, lvalue: Lvalue<H>, pattern: PatternRef<H>) -> MatchPair<H> {
+    pub fn match_pair(&mut self,
+                      lvalue: Lvalue<'tcx>,
+                      pattern: PatternRef<'tcx>)
+                      -> MatchPair<'tcx> {
         let pattern = self.hir.mirror(pattern);
         MatchPair::new(lvalue, pattern)
     }
@@ -47,23 +50,24 @@ impl<H:Hair> Builder<H> {
     ///
     /// and creates a match pair `tmp0 @ s`
     pub fn prefix_suffix_slice(&mut self,
-                               match_pairs: &mut Vec<MatchPair<H>>,
+                               match_pairs: &mut Vec<MatchPair<'tcx>>,
                                block: BasicBlock,
-                               lvalue: Lvalue<H>,
-                               prefix: Vec<PatternRef<H>>,
-                               opt_slice: Option<PatternRef<H>>,
-                               suffix: Vec<PatternRef<H>>)
-                               -> BlockAnd<()>
-    {
+                               lvalue: Lvalue<'tcx>,
+                               prefix: Vec<PatternRef<'tcx>>,
+                               opt_slice: Option<PatternRef<'tcx>>,
+                               suffix: Vec<PatternRef<'tcx>>)
+                               -> BlockAnd<()> {
         // If there is a `..P` pattern, create a temporary `t0` for
         // the slice and then a match pair `t0 @ P`:
         if let Some(slice) = opt_slice {
             let slice = self.hir.mirror(slice);
             let prefix_len = prefix.len();
             let suffix_len = suffix.len();
-            let rvalue = Rvalue::Slice { input: lvalue.clone(),
-                                         from_start: prefix_len,
-                                         from_end: suffix_len };
+            let rvalue = Rvalue::Slice {
+                input: lvalue.clone(),
+                from_start: prefix_len,
+                from_end: suffix_len,
+            };
             let temp = self.temp(slice.ty.clone()); // no need to schedule drop, temp is always copy
             self.cfg.push_assign(block, slice.span, &temp, rvalue);
             match_pairs.push(MatchPair::new(temp, slice));
@@ -76,11 +80,10 @@ impl<H:Hair> Builder<H> {
 
     /// Helper for `prefix_suffix_slice` which just processes the prefix and suffix.
     fn prefix_suffix(&mut self,
-                     match_pairs: &mut Vec<MatchPair<H>>,
-                     lvalue: Lvalue<H>,
-                     prefix: Vec<PatternRef<H>>,
-                     suffix: Vec<PatternRef<H>>)
-    {
+                     match_pairs: &mut Vec<MatchPair<'tcx>>,
+                     lvalue: Lvalue<'tcx>,
+                     prefix: Vec<PatternRef<'tcx>>,
+                     suffix: Vec<PatternRef<'tcx>>) {
         let min_length = prefix.len() + suffix.len();
         assert!(min_length < u32::MAX as usize);
         let min_length = min_length as u32;
@@ -118,8 +121,11 @@ impl<H:Hair> Builder<H> {
     }
 }
 
-impl<H:Hair> MatchPair<H> {
-    pub fn new(lvalue: Lvalue<H>, pattern: Pattern<H>) -> MatchPair<H> {
-        MatchPair { lvalue: lvalue, pattern: pattern }
+impl<'tcx> MatchPair<'tcx> {
+    pub fn new(lvalue: Lvalue<'tcx>, pattern: Pattern<'tcx>) -> MatchPair<'tcx> {
+        MatchPair {
+            lvalue: lvalue,
+            pattern: pattern,
+        }
     }
 }
index 1c44988e4b407060071d2fcaa5db68dba4949158..86b6df19b77e73a55f0aae1e902c83bd7272093c 100644 (file)
 use build::Builder;
 use hair::*;
 use repr::*;
-
+use rustc::middle::ty::Ty;
 use std::u32;
+use syntax::codemap::Span;
 
-impl<H:Hair> Builder<H> {
+impl<'a,'tcx> Builder<'a,'tcx> {
     /// Add a new temporary value of type `ty` storing the result of
     /// evaluating `expr`.
     ///
     /// NB: **No cleanup is scheduled for this temporary.** You should
     /// call `schedule_drop` once the temporary is initialized.
-    pub fn temp(&mut self, ty: H::Ty) -> Lvalue<H> {
+    pub fn temp(&mut self, ty: Ty<'tcx>) -> Lvalue<'tcx> {
         let index = self.temp_decls.len();
         self.temp_decls.push(TempDecl { ty: ty });
         assert!(index < (u32::MAX) as usize);
@@ -33,46 +34,44 @@ impl<H:Hair> Builder<H> {
         lvalue
     }
 
-    pub fn push_constant(&mut self,
-                         block: BasicBlock,
-                         span: H::Span,
-                         ty: H::Ty,
-                         constant: Constant<H>)
-                         -> Lvalue<H> {
-        let temp = self.temp(ty);
+    pub fn push_literal(&mut self,
+                        block: BasicBlock,
+                        span: Span,
+                        ty: Ty<'tcx>,
+                        literal: Literal<'tcx>)
+                        -> Lvalue<'tcx> {
+        let temp = self.temp(ty.clone());
+        let constant = Constant {
+            span: span,
+            ty: ty,
+            literal: literal,
+        };
         self.cfg.push_assign_constant(block, span, &temp, constant);
         temp
     }
 
-    pub fn push_usize(&mut self,
-                      block: BasicBlock,
-                      span: H::Span,
-                      value: usize)
-                      -> Lvalue<H> {
+    pub fn push_usize(&mut self, block: BasicBlock, span: Span, value: usize) -> Lvalue<'tcx> {
         let usize_ty = self.hir.usize_ty();
         let temp = self.temp(usize_ty);
         self.cfg.push_assign_constant(
             block, span, &temp,
             Constant {
                 span: span,
-                kind: ConstantKind::Literal(Literal::Uint { bits: IntegralBits::BSize,
-                                                            value: value as u64 }),
+                ty: self.hir.usize_ty(),
+                literal: self.hir.usize_literal(value),
             });
         temp
     }
 
     pub fn push_item_ref(&mut self,
                          block: BasicBlock,
-                         span: H::Span,
-                         item_ref: ItemRef<H>)
-                         -> Lvalue<H> {
-        let constant = Constant {
-            span: span,
-            kind: ConstantKind::Literal(Literal::Item {
-                def_id: item_ref.def_id,
-                substs: item_ref.substs
-            })
+                         span: Span,
+                         item_ref: ItemRef<'tcx>)
+                         -> Lvalue<'tcx> {
+        let literal = Literal::Item {
+            def_id: item_ref.def_id,
+            substs: item_ref.substs,
         };
-        self.push_constant(block, span, item_ref.ty, constant)
+        self.push_literal(block, span, item_ref.ty, literal)
     }
 }
index 9d00044c6609daca916698aae5944cd1ab9e4f32..857540e2109c02e7a51b7b45e25e385c238038de 100644 (file)
@@ -8,24 +8,30 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use hair::{self, Hair};
+use hair;
+use rustc::middle::region::CodeExtent;
+use rustc::middle::ty::Ty;
 use rustc_data_structures::fnv::FnvHashMap;
+use rustc_front::hir;
 use repr::*;
-
-struct Builder<H:Hair> {
-    hir: H,
-    extents: FnvHashMap<H::CodeExtent, Vec<GraphExtent>>,
-    cfg: CFG<H>,
-    scopes: Vec<scope::Scope<H>>,
-    loop_scopes: Vec<scope::LoopScope<H>>,
-    unit_temp: Lvalue<H>,
-    var_decls: Vec<VarDecl<H>>,
-    var_indices: FnvHashMap<H::VarId, u32>,
-    temp_decls: Vec<TempDecl<H>>,
+use syntax::ast;
+use syntax::codemap::Span;
+use tcx::{Cx, PatNode};
+
+struct Builder<'a, 'tcx: 'a> {
+    hir: Cx<'a, 'tcx>,
+    extents: FnvHashMap<CodeExtent, Vec<GraphExtent>>,
+    cfg: CFG<'tcx>,
+    scopes: Vec<scope::Scope<'tcx>>,
+    loop_scopes: Vec<scope::LoopScope>,
+    unit_temp: Lvalue<'tcx>,
+    var_decls: Vec<VarDecl<'tcx>>,
+    var_indices: FnvHashMap<ast::NodeId, u32>,
+    temp_decls: Vec<TempDecl<'tcx>>,
 }
 
-struct CFG<H:Hair> {
-    basic_blocks: Vec<BasicBlockData<H>>
+struct CFG<'tcx> {
+    basic_blocks: Vec<BasicBlockData<'tcx>>,
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -69,18 +75,18 @@ macro_rules! unpack {
 ///////////////////////////////////////////////////////////////////////////
 // construct() -- the main entry point for building MIR for a function
 
-pub fn construct<H:Hair>(mut hir: H,
-                        _span: H::Span,
-                        implicit_arguments: Vec<H::Ty>,
-                        explicit_arguments: Vec<(H::Ty, H::Pattern)>,
-                        argument_extent: H::CodeExtent,
-                        ast_block: H::Block)
-                        -> Mir<H> {
+pub fn construct<'a, 'tcx>(mut hir: Cx<'a, 'tcx>,
+                           _span: Span,
+                           implicit_arguments: Vec<Ty<'tcx>>,
+                           explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>,
+                           argument_extent: CodeExtent,
+                           ast_block: &'tcx hir::Block)
+                           -> Mir<'tcx> {
     let cfg = CFG { basic_blocks: vec![] };
 
     // it's handy to have a temporary of type `()` sometimes, so make
     // one from the start and keep it available
-    let temp_decls = vec![TempDecl::<H> { ty: hir.unit_ty() }];
+    let temp_decls = vec![TempDecl::<'tcx> { ty: hir.unit_ty() }];
     let unit_temp = Lvalue::Temp(0);
 
     let mut builder = Builder {
@@ -109,7 +115,7 @@ pub fn construct<H:Hair>(mut hir: H,
     builder.cfg.terminate(block, Terminator::Goto { target: END_BLOCK });
     builder.cfg.terminate(END_BLOCK, Terminator::Return);
 
-    Mir  {
+    Mir {
         basic_blocks: builder.cfg.basic_blocks,
         extents: builder.extents,
         var_decls: builder.var_decls,
@@ -118,14 +124,14 @@ pub fn construct<H:Hair>(mut hir: H,
     }
 }
 
-impl<H:Hair> Builder<H> {
+impl<'a,'tcx> Builder<'a,'tcx> {
     fn args_and_body(&mut self,
                      mut block: BasicBlock,
-                     implicit_arguments: Vec<H::Ty>,
-                     explicit_arguments: Vec<(H::Ty, H::Pattern)>,
-                     argument_extent: H::CodeExtent,
-                     ast_block: H::Block)
-                     -> BlockAnd<Vec<ArgDecl<H>>>
+                     implicit_arguments: Vec<Ty<'tcx>>,
+                     explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>,
+                     argument_extent: CodeExtent,
+                     ast_block: &'tcx hir::Block)
+                     -> BlockAnd<Vec<ArgDecl<'tcx>>>
     {
         self.in_scope(argument_extent, block, |this| {
             let arg_decls = {
@@ -171,4 +177,3 @@ mod matches;
 mod misc;
 mod scope;
 mod stmt;
-
index 87a4731ac74be68bd4fc519715af80250813c109..cecd610ff725ff39c45a409c12bc842cebb747f4 100644 (file)
@@ -12,7 +12,7 @@
 Managing the scope stack. The scopes are tied to lexical scopes, so as
 we descend the HAIR, we push a scope on the stack, translate ite
 contents, and then pop it off. Every scope is named by a
-`H::CodeExtent`.
+`CodeExtent`.
 
 ### SEME Regions
 
@@ -23,7 +23,7 @@ via a `break` or `return` or just by fallthrough, that marks an exit
 from the scope. Each lexical scope thus corresponds to a single-entry,
 multiple-exit (SEME) region in the control-flow graph.
 
-For now, we keep a mapping from each `H::CodeExtent` to its
+For now, we keep a mapping from each `CodeExtent` to its
 corresponding SEME region for later reference (see caveat in next
 paragraph). This is because region scopes are tied to
 them. Eventually, when we shift to non-lexical lifetimes, three should
@@ -87,37 +87,41 @@ should go to.
 */
 
 use build::{BlockAnd, Builder, CFG};
-use hair::Hair;
 use repr::*;
+use rustc::middle::region::CodeExtent;
+use rustc::middle::ty::Ty;
+use syntax::codemap::Span;
 
-pub struct Scope<H:Hair> {
-    extent: H::CodeExtent,
+pub struct Scope<'tcx> {
+    extent: CodeExtent,
     exits: Vec<ExecutionPoint>,
-    drops: Vec<(DropKind, H::Span, Lvalue<H>)>,
+    drops: Vec<(DropKind, Span, Lvalue<'tcx>)>,
     cached_block: Option<BasicBlock>,
 }
 
 #[derive(Clone, Debug)]
-pub struct LoopScope<H:Hair> {
-    pub extent: H::CodeExtent,      // extent of the loop
+pub struct LoopScope {
+    pub extent: CodeExtent, // extent of the loop
     pub continue_block: BasicBlock, // where to go on a `loop`
-    pub break_block: BasicBlock,    // where to go on a `break
+    pub break_block: BasicBlock, // where to go on a `break
 }
 
-impl<H:Hair> Builder<H> {
+impl<'a,'tcx> Builder<'a,'tcx> {
     /// Start a loop scope, which tracks where `continue` and `break`
     /// should branch to. See module comment for more details.
-    pub fn in_loop_scope<F,R>(&mut self,
-                              loop_block: BasicBlock,
-                              break_block: BasicBlock,
-                              f: F)
-                              -> BlockAnd<R>
-        where F: FnOnce(&mut Builder<H>) -> BlockAnd<R>
+    pub fn in_loop_scope<F, R>(&mut self,
+                               loop_block: BasicBlock,
+                               break_block: BasicBlock,
+                               f: F)
+                               -> BlockAnd<R>
+        where F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>
     {
         let extent = self.extent_of_innermost_scope().unwrap();
-        let loop_scope = LoopScope::<H> { extent: extent.clone(),
-                                          continue_block: loop_block,
-                                          break_block: break_block };
+        let loop_scope = LoopScope {
+            extent: extent.clone(),
+            continue_block: loop_block,
+            break_block: break_block,
+        };
         self.loop_scopes.push(loop_scope);
         let r = f(self);
         assert!(self.loop_scopes.pop().unwrap().extent == extent);
@@ -126,12 +130,8 @@ impl<H:Hair> Builder<H> {
 
     /// Start a scope. The closure `f` should translate the contents
     /// of the scope. See module comment for more details.
-    pub fn in_scope<F,R>(&mut self,
-                         extent: H::CodeExtent,
-                         block: BasicBlock,
-                         f: F)
-                         -> BlockAnd<R>
-        where F: FnOnce(&mut Builder<H>) -> BlockAnd<R>
+    pub fn in_scope<F, R>(&mut self, extent: CodeExtent, block: BasicBlock, f: F) -> BlockAnd<R>
+        where F: FnOnce(&mut Builder<'a, 'tcx>) -> BlockAnd<R>
     {
         debug!("in_scope(extent={:?}, block={:?})", extent, block);
 
@@ -171,18 +171,24 @@ impl<H:Hair> Builder<H> {
     /// exit points.
     fn graph_extent(&self, entry: ExecutionPoint, exits: Vec<ExecutionPoint>) -> GraphExtent {
         if exits.len() == 1 && entry.block == exits[0].block {
-            GraphExtent { entry: entry, exit: GraphExtentExit::Statement(exits[0].statement) }
+            GraphExtent {
+                entry: entry,
+                exit: GraphExtentExit::Statement(exits[0].statement),
+            }
         } else {
-            GraphExtent { entry: entry, exit: GraphExtentExit::Points(exits) }
+            GraphExtent {
+                entry: entry,
+                exit: GraphExtentExit::Points(exits),
+            }
         }
     }
 
     /// Finds the loop scope for a given label. This is used for
     /// resolving `break` and `continue`.
     pub fn find_loop_scope(&mut self,
-                           span: H::Span,
-                           label: Option<H::CodeExtent>)
-                           -> LoopScope<H> {
+                           span: Span,
+                           label: Option<CodeExtent>)
+                           -> LoopScope {
         let loop_scope =
             match label {
                 None => {
@@ -202,7 +208,7 @@ impl<H:Hair> Builder<H> {
 
         match loop_scope {
             Some(loop_scope) => loop_scope.clone(),
-            None => self.hir.span_bug(span, "no enclosing loop scope found?")
+            None => self.hir.span_bug(span, "no enclosing loop scope found?"),
         }
     }
 
@@ -211,8 +217,8 @@ impl<H:Hair> Builder<H> {
     /// needed, as well as tracking this exit for the SEME region. See
     /// module comment for details.
     pub fn exit_scope(&mut self,
-                      span: H::Span,
-                      extent: H::CodeExtent,
+                      span: Span,
+                      extent: CodeExtent,
                       block: BasicBlock,
                       target: BasicBlock) {
         let popped_scopes =
@@ -249,12 +255,11 @@ impl<H:Hair> Builder<H> {
     /// Indicates that `lvalue` should be dropped on exit from
     /// `extent`.
     pub fn schedule_drop(&mut self,
-                         span: H::Span,
-                         extent: H::CodeExtent,
+                         span: Span,
+                         extent: CodeExtent,
                          kind: DropKind,
-                         lvalue: &Lvalue<H>,
-                         lvalue_ty: H::Ty)
-    {
+                         lvalue: &Lvalue<'tcx>,
+                         lvalue_ty: Ty<'tcx>) {
         if self.hir.needs_drop(lvalue_ty, span) {
             match self.scopes.iter_mut().rev().find(|s| s.extent == extent) {
                 Some(scope) => {
@@ -267,18 +272,16 @@ impl<H:Hair> Builder<H> {
         }
     }
 
-    pub fn extent_of_innermost_scope(&self) -> Option<H::CodeExtent> {
+    pub fn extent_of_innermost_scope(&self) -> Option<CodeExtent> {
         self.scopes.last().map(|scope| scope.extent)
     }
 
-    pub fn extent_of_outermost_scope(&self) -> Option<H::CodeExtent> {
+    pub fn extent_of_outermost_scope(&self) -> Option<CodeExtent> {
         self.scopes.first().map(|scope| scope.extent)
     }
 }
 
-fn diverge_cleanup_helper<H:Hair>(cfg: &mut CFG<H>,
-                                 scopes: &mut [Scope<H>])
-                                 -> BasicBlock {
+fn diverge_cleanup_helper<'tcx>(cfg: &mut CFG<'tcx>, scopes: &mut [Scope<'tcx>]) -> BasicBlock {
     let len = scopes.len();
 
     if len == 0 {
index 9d5a83154d4028d37760b15604a743ed035f69f5..01fda2498f7121102ee32ee2f12a8b8e11c84c1d 100644 (file)
@@ -12,15 +12,15 @@ use build::{BlockAnd, Builder};
 use hair::*;
 use repr::*;
 
-impl<H:Hair> Builder<H> {
-    pub fn stmts(&mut self, mut block: BasicBlock, stmts: Vec<StmtRef<H>>) -> BlockAnd<()> {
+impl<'a,'tcx> Builder<'a,'tcx> {
+    pub fn stmts(&mut self, mut block: BasicBlock, stmts: Vec<StmtRef<'tcx>>) -> BlockAnd<()> {
         for stmt in stmts {
             unpack!(block = self.stmt(block, stmt));
         }
         block.unit()
     }
 
-    pub fn stmt(&mut self, mut block: BasicBlock, stmt: StmtRef<H>) -> BlockAnd<()> {
+    pub fn stmt(&mut self, mut block: BasicBlock, stmt: StmtRef<'tcx>) -> BlockAnd<()> {
         let this = self;
         let Stmt { span, kind } = this.hir.mirror(stmt);
         match kind {
@@ -40,7 +40,7 @@ impl<H:Hair> Builder<H> {
             StmtKind::Let { remainder_scope, init_scope, pattern, initializer: None, stmts } => {
                 this.in_scope(remainder_scope, block, |this| {
                     unpack!(block = this.in_scope(init_scope, block, |this| {
-                        this.declare_uninitialized_variables(remainder_scope, pattern);
+                        this.declare_bindings(remainder_scope, pattern);
                         block.unit()
                     }));
                     this.stmts(block, stmts)
diff --git a/src/librustc_mir/dump.rs b/src/librustc_mir/dump.rs
deleted file mode 100644 (file)
index 8e608de..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! An experimental pass that scources for `#[rustc_mir]` attributes,
-//! builds the resulting MIR, and dumps it out into a file for inspection.
-//!
-//! The attribute formats that are currently accepted are:
-//!
-//! - `#[rustc_mir(graphviz="file.gv")]`
-//! - `#[rustc_mir(pretty="file.mir")]`
-
-extern crate syntax;
-extern crate rustc;
-extern crate rustc_front;
-
-use build;
-use dot;
-use repr::Mir;
-use std::fs::File;
-use tcx::{PatNode, Cx};
-
-use self::rustc::middle::def_id::DefId;
-use self::rustc::middle::infer;
-use self::rustc::middle::region::CodeExtentData;
-use self::rustc::middle::ty::{self, Ty};
-use self::rustc::util::common::ErrorReported;
-use self::rustc_front::hir;
-use self::rustc_front::attr::{AttrMetaMethods};
-use self::rustc_front::visit;
-use self::syntax::ast;
-use self::syntax::codemap::Span;
-
-pub fn dump_crate(tcx: &ty::ctxt) {
-    let mut dump = OuterDump { tcx: tcx };
-    visit::walk_crate(&mut dump, tcx.map.krate());
-}
-
-///////////////////////////////////////////////////////////////////////////
-// OuterDump -- walks a crate, looking for fn items and methods to build MIR from
-
-struct OuterDump<'a,'tcx:'a> {
-    tcx: &'a ty::ctxt<'tcx>,
-}
-
-impl<'a, 'tcx> OuterDump<'a, 'tcx> {
-    fn visit_mir<OP>(&self, attributes: &'tcx [hir::Attribute], mut walk_op: OP)
-        where OP: FnMut(&mut InnerDump<'a,'tcx>)
-    {
-        let mut built_mir = false;
-
-        for attr in attributes {
-            if attr.check_name("rustc_mir") {
-                let mut closure_dump = InnerDump { tcx: self.tcx, attr: Some(attr) };
-                walk_op(&mut closure_dump);
-                built_mir = true;
-            }
-        }
-
-        let always_build_mir = self.tcx.sess.opts.always_build_mir;
-        if !built_mir && always_build_mir {
-            let mut closure_dump = InnerDump { tcx: self.tcx, attr: None };
-            walk_op(&mut closure_dump);
-        }
-    }
-}
-
-
-impl<'a, 'tcx> visit::Visitor<'tcx> for OuterDump<'a, 'tcx> {
-    fn visit_item(&mut self, item: &'tcx hir::Item) {
-        self.visit_mir(&item.attrs, |c| visit::walk_item(c, item));
-        visit::walk_item(self, item);
-    }
-
-    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
-        match trait_item.node {
-            hir::MethodTraitItem(_, Some(_)) => {
-                self.visit_mir(&trait_item.attrs, |c| visit::walk_trait_item(c, trait_item));
-            }
-            _ => { }
-        }
-        visit::walk_trait_item(self, trait_item);
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////
-// InnerDump -- dumps MIR for a single fn and its contained closures
-
-struct InnerDump<'a,'tcx:'a> {
-    tcx: &'a ty::ctxt<'tcx>,
-    attr: Option<&'a hir::Attribute>,
-}
-
-impl<'a, 'tcx> visit::Visitor<'tcx> for InnerDump<'a,'tcx> {
-    fn visit_item(&mut self, _: &'tcx hir::Item) {
-        // ignore nested items; they need their own graphviz annotation
-    }
-
-    fn visit_fn(&mut self,
-                fk: visit::FnKind<'tcx>,
-                decl: &'tcx hir::FnDecl,
-                body: &'tcx hir::Block,
-                span: Span,
-                id: ast::NodeId) {
-        let (prefix, implicit_arg_tys) = match fk {
-            visit::FnKind::Closure =>
-                (format!("{}-", id), vec![closure_self_ty(&self.tcx, id, body.id)]),
-            _ =>
-                (format!(""), vec![]),
-        };
-
-        let param_env =
-            ty::ParameterEnvironment::for_item(self.tcx, id);
-
-        let infcx =
-            infer::new_infer_ctxt(self.tcx,
-                                  &self.tcx.tables,
-                                  Some(param_env),
-                                  true);
-
-        match build_mir(Cx::new(&infcx), implicit_arg_tys, id, span, decl, body) {
-            Ok(mir) => {
-                let meta_item_list =
-                    self.attr.iter()
-                             .flat_map(|a| a.meta_item_list())
-                             .flat_map(|l| l.iter());
-                for item in meta_item_list {
-                    if item.check_name("graphviz") {
-                        match item.value_str() {
-                            Some(s) => {
-                                match
-                                    File::create(format!("{}{}", prefix, s))
-                                    .and_then(|ref mut output| dot::render(&mir, output))
-                                {
-                                    Ok(()) => { }
-                                    Err(e) => {
-                                        self.tcx.sess.span_fatal(
-                                            item.span,
-                                            &format!("Error writing graphviz \
-                                                      results to `{}`: {}",
-                                                     s, e));
-                                    }
-                                }
-                            }
-                            None => {
-                                self.tcx.sess.span_err(
-                                    item.span,
-                                    &format!("graphviz attribute requires a path"));
-                            }
-                        }
-                    }
-                }
-            }
-            Err(ErrorReported) => { }
-        }
-
-        visit::walk_fn(self, fk, decl, body, span);
-    }
-}
-
-fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>,
-                         implicit_arg_tys: Vec<Ty<'tcx>>,
-                         fn_id: ast::NodeId,
-                         span: Span,
-                         decl: &'tcx hir::FnDecl,
-                         body: &'tcx hir::Block)
-                         -> Result<Mir<Cx<'a,'tcx>>, ErrorReported> {
-    let arguments =
-        decl.inputs
-            .iter()
-            .map(|arg| {
-                let ty = cx.tcx.node_id_to_type(arg.id);
-                (ty, PatNode::irrefutable(&arg.pat))
-            })
-            .collect();
-
-    let parameter_scope =
-        cx.tcx.region_maps.lookup_code_extent(
-            CodeExtentData::ParameterScope { fn_id: fn_id, body_id: body.id });
-    Ok(build::construct(cx,
-                        span,
-                        implicit_arg_tys,
-                        arguments,
-                        parameter_scope,
-                        body))
-}
-
-fn closure_self_ty<'a,'tcx>(tcx: &ty::ctxt<'tcx>,
-                            closure_expr_id: ast::NodeId,
-                            body_id: ast::NodeId)
-                            -> Ty<'tcx>
-{
-    let closure_ty = tcx.node_id_to_type(closure_expr_id);
-
-    // We're just hard-coding the idea that the signature will be
-    // &self or &mut self and hence will have a bound region with
-    // number 0, hokey.
-    let region =
-        ty::Region::ReFree(
-            ty::FreeRegion {
-                scope: tcx.region_maps.item_extent(body_id),
-                bound_region: ty::BoundRegion::BrAnon(0)
-            });
-    let region =
-        tcx.mk_region(region);
-
-    match tcx.closure_kind(DefId::local(closure_expr_id)) {
-        ty::ClosureKind::FnClosureKind =>
-            tcx.mk_ref(region,
-                       ty::TypeAndMut { ty: closure_ty,
-                                        mutbl: hir::MutImmutable }),
-        ty::ClosureKind::FnMutClosureKind =>
-            tcx.mk_ref(region,
-                       ty::TypeAndMut { ty: closure_ty,
-                                        mutbl: hir::MutMutable }),
-        ty::ClosureKind::FnOnceClosureKind =>
-            closure_ty
-    }
-}
index 01ccf20ae06545ddf31f60f96f89f24f1cd89c15..9da05a27e898deefd2d5887e4b4d78027fe37fe6 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use dot;
-use hair::Hair;
 use repr::*;
 use std::borrow::IntoCow;
 
@@ -20,7 +19,7 @@ pub struct EdgeIndex {
     index: usize,
 }
 
-impl<'a,H:Hair> dot::Labeller<'a, BasicBlock, EdgeIndex> for Mir<H> {
+impl<'a,'tcx> dot::Labeller<'a, BasicBlock, EdgeIndex> for Mir<'tcx> {
     fn graph_id(&'a self) -> dot::Id<'a> {
         dot::Id::new("Mir").unwrap()
     }
@@ -62,7 +61,7 @@ impl<'a,H:Hair> dot::Labeller<'a, BasicBlock, EdgeIndex> for Mir<H> {
     }
 }
 
-impl<'a,H:Hair> dot::GraphWalk<'a, BasicBlock, EdgeIndex> for Mir<H> {
+impl<'a,'tcx> dot::GraphWalk<'a, BasicBlock, EdgeIndex> for Mir<'tcx> {
     fn nodes(&'a self) -> dot::Nodes<'a, BasicBlock> {
         self.all_basic_blocks().into_cow()
     }
@@ -71,15 +70,18 @@ impl<'a,H:Hair> dot::GraphWalk<'a, BasicBlock, EdgeIndex> for Mir<H> {
         self.all_basic_blocks()
             .into_iter()
             .flat_map(|source| {
-                self.basic_block_data(source).terminator
-                                             .successors()
-                                             .iter()
-                                             .enumerate()
-                                             .map(move |(index, &target)| {
-                                                 EdgeIndex { source: source,
-                                                             target: target,
-                                                             index: index }
-                                             })
+                self.basic_block_data(source)
+                    .terminator
+                    .successors()
+                    .iter()
+                    .enumerate()
+                    .map(move |(index, &target)| {
+                        EdgeIndex {
+                            source: source,
+                            target: target,
+                            index: index,
+                        }
+                    })
             })
             .collect::<Vec<_>>()
             .into_cow()
@@ -119,7 +121,10 @@ fn all_to_subscript(header: &str, mut text: String) -> String {
     /// Returns an updated string if changes were made, else None.
     fn to_subscript1(header: &str, text: &str, offset: &mut usize) -> Option<String> {
         let a = match text[*offset..].find(header) {
-            None => { *offset = text.len(); return None; }
+            None => {
+                *offset = text.len();
+                return None;
+            }
             Some(a) => a + *offset,
         };
 
@@ -142,8 +147,12 @@ fn all_to_subscript(header: &str, mut text: String) -> String {
         result.push_str(&text[..b]);
 
         while let Some(c) = chars.next() {
-            if c == ')' { break; }
-            if !c.is_digit(10) { return None; }
+            if c == ')' {
+                break;
+            }
+            if !c.is_digit(10) {
+                return None;
+            }
 
             // 0x208 is _0 in unicode, 0x209 is _1, etc
             const SUBSCRIPTS: &'static str = "₀₁₂₃₄₅₆₇₈₉";
index c63a0348337129a568a7f05e1906c5f7dfd63e2e..641cbae4be27101497259972a4d4d237ef6d5578 100644 (file)
 //! structures.
 
 use repr::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp};
-use std::fmt::Debug;
-use std::hash::Hash;
-
-pub trait Hair: Sized+Debug+Clone+Eq+Hash { // (*)
-
-    // (*) the `Sized` and Debug` bounds are the only ones that really
-    // make sense.  The rest are just there so that we can
-    // `#[derive(Clone)]` on things that are parameterized over
-    // `H:HAIR`. It's kind of lame.
-
-    type VarId: Copy+Debug+Eq+Hash;                              // e.g., NodeId for a variable
-    type DefId: Copy+Debug+Eq+Hash;                              // e.g., DefId
-    type AdtDef: Copy+Debug+Eq+Hash;                             // e.g., AdtDef<'tcx>
-    type Name: Copy+Debug+Eq+Hash;                               // e.g., ast::Name
-    type Ident: Copy+Debug+Eq+Hash;                              // e.g., ast::Ident
-    type InternedString: Clone+Debug+Eq+Hash;                    // e.g., InternedString
-    type Bytes: Clone+Debug+Eq+Hash;                             // e.g., Rc<Vec<u8>>
-    type Span: Copy+Debug+Eq;                                    // e.g., syntax::codemap::Span
-    type Projection: Clone+Debug+Eq;                             // e.g., ty::ProjectionTy<'tcx>
-    type Substs: Clone+Debug+Eq;                                 // e.g., substs::Substs<'tcx>
-    type ClosureSubsts: Clone+Debug+Eq;                          // e.g., ty::ClosureSubsts<'tcx>
-    type Ty: Clone+Debug+Eq;                                     // e.g., ty::Ty<'tcx>
-    type Region: Copy+Debug;                                     // e.g., ty::Region
-    type CodeExtent: Copy+Debug+Hash+Eq;                         // e.g., region::CodeExtent
-    type Pattern: Clone+Debug+Mirror<Self,Output=Pattern<Self>>; // e.g., &P<ast::Pat>
-    type Expr: Clone+Debug+Mirror<Self,Output=Expr<Self>>;       // e.g., &P<ast::Expr>
-    type Stmt: Clone+Debug+Mirror<Self,Output=Stmt<Self>>;       // e.g., &P<ast::Stmt>
-    type Block: Clone+Debug+Mirror<Self,Output=Block<Self>>;     // e.g., &P<ast::Block>
-    type InlineAsm: Clone+Debug+Eq+Hash;                         // e.g., ast::InlineAsm
-
-    /// Normalizes `ast` into the appropriate `mirror` type.
-    fn mirror<M:Mirror<Self>>(&mut self, ast: M) -> M::Output {
-        ast.make_mirror(self)
-    }
-
-    /// Returns the unit type `()`
-    fn unit_ty(&mut self) -> Self::Ty;
-
-    /// Returns the type `usize`.
-    fn usize_ty(&mut self) -> Self::Ty;
-
-    /// Returns the type `bool`.
-    fn bool_ty(&mut self) -> Self::Ty;
-
-    /// Returns a reference to `PartialEq::<T,T>::eq`
-    fn partial_eq(&mut self, ty: Self::Ty) -> ItemRef<Self>;
-
-    /// Returns a reference to `PartialOrd::<T,T>::le`
-    fn partial_le(&mut self, ty: Self::Ty) -> ItemRef<Self>;
-
-    /// Returns the number of variants for the given enum
-    fn num_variants(&mut self, adt: Self::AdtDef) -> usize;
-
-    fn fields(&mut self, adt: Self::AdtDef, variant_index: usize) -> Vec<Field<Self>>;
-
-    /// true if a value of type `ty` (may) need to be dropped; this
-    /// may return false even for non-Copy types if there is no
-    /// destructor to execute. If correct result is not known, may be
-    /// approximated by returning `true`; this will result in more
-    /// drops but not incorrect code.
-    fn needs_drop(&mut self, ty: Self::Ty, span: Self::Span) -> bool;
-
-    /// Report an internal inconsistency.
-    fn span_bug(&mut self, span: Self::Span, message: &str) -> !;
-}
+use rustc::middle::def_id::DefId;
+use rustc::middle::region::CodeExtent;
+use rustc::middle::subst::Substs;
+use rustc::middle::ty::{AdtDef, ClosureSubsts, Region, Ty};
+use rustc_front::hir;
+use syntax::ast;
+use syntax::codemap::Span;
+use tcx::{Cx, PatNode};
 
 #[derive(Clone, Debug)]
-pub struct ItemRef<H:Hair> {
-    pub ty: H::Ty,
-    pub def_id: H::DefId,
-    pub substs: H::Substs,
+pub struct ItemRef<'tcx> {
+    pub ty: Ty<'tcx>,
+    pub def_id: DefId,
+    pub substs: &'tcx Substs<'tcx>,
 }
 
 #[derive(Clone, Debug)]
-pub struct Block<H:Hair> {
-    pub extent: H::CodeExtent,
-    pub span: H::Span,
-    pub stmts: Vec<StmtRef<H>>,
-    pub expr: Option<ExprRef<H>>,
+pub struct Block<'tcx> {
+    pub extent: CodeExtent,
+    pub span: Span,
+    pub stmts: Vec<StmtRef<'tcx>>,
+    pub expr: Option<ExprRef<'tcx>>,
 }
 
 #[derive(Clone, Debug)]
-pub enum StmtRef<H:Hair> {
-    Hair(H::Stmt),
-    Mirror(Box<Stmt<H>>),
+pub enum StmtRef<'tcx> {
+    Hair(&'tcx hir::Stmt),
+    Mirror(Box<Stmt<'tcx>>),
 }
 
 #[derive(Clone, Debug)]
-pub struct Stmt<H:Hair> {
-    pub span: H::Span,
-    pub kind: StmtKind<H>,
+pub struct Stmt<'tcx> {
+    pub span: Span,
+    pub kind: StmtKind<'tcx>,
 }
 
 #[derive(Clone, Debug)]
-pub enum StmtKind<H:Hair> {
+pub enum StmtKind<'tcx> {
     Expr {
         /// scope for this statement; may be used as lifetime of temporaries
-        scope: H::CodeExtent,
+        scope: CodeExtent,
 
         /// expression being evaluated in this statement
-        expr: ExprRef<H>
+        expr: ExprRef<'tcx>,
     },
 
     Let {
         /// scope for variables bound in this let; covers this and
         /// remaining statements in block
-        remainder_scope: H::CodeExtent,
+        remainder_scope: CodeExtent,
 
         /// scope for the initialization itself; might be used as
         /// lifetime of temporaries
-        init_scope: H::CodeExtent,
+        init_scope: CodeExtent,
 
         /// let <PAT> = ...
-        pattern: PatternRef<H>,
+        pattern: PatternRef<'tcx>,
 
         /// let pat = <INIT> ...
-        initializer: Option<ExprRef<H>>,
+        initializer: Option<ExprRef<'tcx>>,
 
         /// let pat = init; <STMTS>
-        stmts: Vec<StmtRef<H>>
+        stmts: Vec<StmtRef<'tcx>>,
     },
 }
 
-// The Hair trait implementor translates their expressions (`H::Expr`)
+// The Hair trait implementor translates their expressions (`&'tcx H::Expr`)
 // into instances of this `Expr` enum. This translation can be done
 // basically as lazilly or as eagerly as desired: every recursive
-// reference to an expression in this enum is an `ExprRef<H>`, which
+// reference to an expression in this enum is an `ExprRef<'tcx>`, which
 // may in turn be another instance of this enum (boxed), or else an
-// untranslated `H::Expr`. Note that instances of `Expr` are very
+// untranslated `&'tcx H::Expr`. Note that instances of `Expr` are very
 // shortlived. They are created by `Hair::to_expr`, analyzed and
 // converted into MIR, and then discarded.
 //
@@ -153,180 +96,284 @@ pub enum StmtKind<H:Hair> {
 // example, method calls and overloaded operators are absent: they are
 // expected to be converted into `Expr::Call` instances.
 #[derive(Clone, Debug)]
-pub struct Expr<H:Hair> {
+pub struct Expr<'tcx> {
     // type of this expression
-    pub ty: H::Ty,
+    pub ty: Ty<'tcx>,
 
     // lifetime of this expression if it should be spilled into a
     // temporary; should be None only if in a constant context
-    pub temp_lifetime: Option<H::CodeExtent>,
+    pub temp_lifetime: Option<CodeExtent>,
 
     // span of the expression in the source
-    pub span: H::Span,
+    pub span: Span,
 
     // kind of expression
-    pub kind: ExprKind<H>,
+    pub kind: ExprKind<'tcx>,
 }
 
 #[derive(Clone, Debug)]
-pub enum ExprKind<H:Hair> {
-    Scope { extent: H::CodeExtent, value: ExprRef<H> },
-    Paren { arg: ExprRef<H> }, // ugh. should be able to remove this!
-    Box { place: Option<ExprRef<H>>, value: ExprRef<H> },
-    Call { fun: ExprRef<H>, args: Vec<ExprRef<H>> },
-    Deref { arg: ExprRef<H> }, // NOT overloaded!
-    Binary { op: BinOp, lhs: ExprRef<H>, rhs: ExprRef<H> }, // NOT overloaded!
-    LogicalOp { op: LogicalOp, lhs: ExprRef<H>, rhs: ExprRef<H> },
-    Unary { op: UnOp, arg: ExprRef<H> }, // NOT overloaded!
-    Cast { source: ExprRef<H> },
-    ReifyFnPointer { source: ExprRef<H> },
-    UnsafeFnPointer { source: ExprRef<H> },
-    Unsize { source: ExprRef<H> },
-    If { condition: ExprRef<H>, then: ExprRef<H>, otherwise: Option<ExprRef<H>> },
-    Loop { condition: Option<ExprRef<H>>, body: ExprRef<H>, },
-    Match { discriminant: ExprRef<H>, arms: Vec<Arm<H>> },
-    Block { body: H::Block },
-    Assign { lhs: ExprRef<H>, rhs: ExprRef<H> },
-    AssignOp { op: BinOp, lhs: ExprRef<H>, rhs: ExprRef<H> },
-    Field { lhs: ExprRef<H>, name: Field<H> },
-    Index { lhs: ExprRef<H>, index: ExprRef<H> },
-    VarRef { id: H::VarId },
+pub enum ExprKind<'tcx> {
+    Scope {
+        extent: CodeExtent,
+        value: ExprRef<'tcx>,
+    },
+    Box {
+        value: ExprRef<'tcx>,
+    },
+    Call {
+        fun: ExprRef<'tcx>,
+        args: Vec<ExprRef<'tcx>>,
+    },
+    Deref {
+        arg: ExprRef<'tcx>,
+    }, // NOT overloaded!
+    Binary {
+        op: BinOp,
+        lhs: ExprRef<'tcx>,
+        rhs: ExprRef<'tcx>,
+    }, // NOT overloaded!
+    LogicalOp {
+        op: LogicalOp,
+        lhs: ExprRef<'tcx>,
+        rhs: ExprRef<'tcx>,
+    },
+    Unary {
+        op: UnOp,
+        arg: ExprRef<'tcx>,
+    }, // NOT overloaded!
+    Cast {
+        source: ExprRef<'tcx>,
+    },
+    ReifyFnPointer {
+        source: ExprRef<'tcx>,
+    },
+    UnsafeFnPointer {
+        source: ExprRef<'tcx>,
+    },
+    Unsize {
+        source: ExprRef<'tcx>,
+    },
+    If {
+        condition: ExprRef<'tcx>,
+        then: ExprRef<'tcx>,
+        otherwise: Option<ExprRef<'tcx>>,
+    },
+    Loop {
+        condition: Option<ExprRef<'tcx>>,
+        body: ExprRef<'tcx>,
+    },
+    Match {
+        discriminant: ExprRef<'tcx>,
+        arms: Vec<Arm<'tcx>>,
+    },
+    Block {
+        body: &'tcx hir::Block,
+    },
+    Assign {
+        lhs: ExprRef<'tcx>,
+        rhs: ExprRef<'tcx>,
+    },
+    AssignOp {
+        op: BinOp,
+        lhs: ExprRef<'tcx>,
+        rhs: ExprRef<'tcx>,
+    },
+    Field {
+        lhs: ExprRef<'tcx>,
+        name: Field,
+    },
+    Index {
+        lhs: ExprRef<'tcx>,
+        index: ExprRef<'tcx>,
+    },
+    VarRef {
+        id: ast::NodeId,
+    },
     SelfRef, // first argument, used for self in a closure
-    StaticRef { id: H::DefId },
-    Borrow { region: H::Region, borrow_kind: BorrowKind, arg: ExprRef<H> },
-    Break { label: Option<H::CodeExtent> },
-    Continue { label: Option<H::CodeExtent> },
-    Return { value: Option<ExprRef<H>> },
-    Repeat { value: ExprRef<H>, count: ExprRef<H> },
-    Vec { fields: Vec<ExprRef<H>> },
-    Tuple { fields: Vec<ExprRef<H>> },
-    Adt { adt_def: H::AdtDef,
-          variant_index: usize,
-          substs: H::Substs,
-          fields: Vec<FieldExprRef<H>>,
-          base: Option<ExprRef<H>> },
-    Closure { closure_id: H::DefId, substs: H::ClosureSubsts,
-              upvars: Vec<ExprRef<H>> },
-    Literal { literal: Literal<H> },
-    InlineAsm { asm: H::InlineAsm },
+    StaticRef {
+        id: DefId,
+    },
+    Borrow {
+        region: Region,
+        borrow_kind: BorrowKind,
+        arg: ExprRef<'tcx>,
+    },
+    Break {
+        label: Option<CodeExtent>,
+    },
+    Continue {
+        label: Option<CodeExtent>,
+    },
+    Return {
+        value: Option<ExprRef<'tcx>>,
+    },
+    Repeat {
+        value: ExprRef<'tcx>,
+        count: ExprRef<'tcx>,
+    },
+    Vec {
+        fields: Vec<ExprRef<'tcx>>,
+    },
+    Tuple {
+        fields: Vec<ExprRef<'tcx>>,
+    },
+    Adt {
+        adt_def: AdtDef<'tcx>,
+        variant_index: usize,
+        substs: &'tcx Substs<'tcx>,
+        fields: Vec<FieldExprRef<'tcx>>,
+        base: Option<ExprRef<'tcx>>,
+    },
+    Closure {
+        closure_id: DefId,
+        substs: &'tcx ClosureSubsts<'tcx>,
+        upvars: Vec<ExprRef<'tcx>>,
+    },
+    Literal {
+        literal: Literal<'tcx>,
+    },
+    InlineAsm {
+        asm: &'tcx hir::InlineAsm,
+    },
 }
 
 #[derive(Clone, Debug)]
-pub enum ExprRef<H:Hair> {
-    Hair(H::Expr),
-    Mirror(Box<Expr<H>>),
+pub enum ExprRef<'tcx> {
+    Hair(&'tcx hir::Expr),
+    Mirror(Box<Expr<'tcx>>),
 }
 
 #[derive(Clone, Debug)]
-pub struct FieldExprRef<H:Hair> {
-    pub name: Field<H>,
-    pub expr: ExprRef<H>,
+pub struct FieldExprRef<'tcx> {
+    pub name: Field,
+    pub expr: ExprRef<'tcx>,
 }
 
 #[derive(Clone, Debug)]
-pub struct Arm<H:Hair> {
-    pub patterns: Vec<PatternRef<H>>,
-    pub guard: Option<ExprRef<H>>,
-    pub body: ExprRef<H>,
+pub struct Arm<'tcx> {
+    pub patterns: Vec<PatternRef<'tcx>>,
+    pub guard: Option<ExprRef<'tcx>>,
+    pub body: ExprRef<'tcx>,
 }
 
 #[derive(Clone, Debug)]
-pub struct Pattern<H:Hair> {
-    pub ty: H::Ty,
-    pub span: H::Span,
-    pub kind: PatternKind<H>,
+pub struct Pattern<'tcx> {
+    pub ty: Ty<'tcx>,
+    pub span: Span,
+    pub kind: PatternKind<'tcx>,
 }
 
 #[derive(Copy, Clone, Debug)]
 pub enum LogicalOp {
     And,
-    Or
+    Or,
 }
 
 #[derive(Clone, Debug)]
-pub enum PatternKind<H:Hair> {
+pub enum PatternKind<'tcx> {
     Wild,
 
     // x, ref x, x @ P, etc
-    Binding { mutability: Mutability,
-              name: H::Ident,
-              mode: BindingMode<H>,
-              var: H::VarId,
-              ty: H::Ty,
-              subpattern: Option<PatternRef<H>> },
+    Binding {
+        mutability: Mutability,
+        name: ast::Name,
+        mode: BindingMode,
+        var: ast::NodeId,
+        ty: Ty<'tcx>,
+        subpattern: Option<PatternRef<'tcx>>,
+    },
 
     // Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants
-    Variant { adt_def: H::AdtDef, variant_index: usize, subpatterns: Vec<FieldPatternRef<H>> },
+    Variant {
+        adt_def: AdtDef<'tcx>,
+        variant_index: usize,
+        subpatterns: Vec<FieldPatternRef<'tcx>>,
+    },
 
     // (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant
-    Leaf { subpatterns: Vec<FieldPatternRef<H>> },
+    Leaf {
+        subpatterns: Vec<FieldPatternRef<'tcx>>,
+    },
 
-    Deref { subpattern: PatternRef<H> }, // box P, &P, &mut P, etc
+    Deref {
+        subpattern: PatternRef<'tcx>,
+    }, // box P, &P, &mut P, etc
 
-    Constant { expr: ExprRef<H> },
+    Constant {
+        value: Literal<'tcx>,
+    },
 
-    Range { lo: ExprRef<H>, hi: ExprRef<H> },
+    Range {
+        lo: Literal<'tcx>,
+        hi: Literal<'tcx>,
+    },
 
     // matches against a slice, checking the length and extracting elements
-    Slice { prefix: Vec<PatternRef<H>>,
-            slice: Option<PatternRef<H>>,
-            suffix: Vec<PatternRef<H>> },
+    Slice {
+        prefix: Vec<PatternRef<'tcx>>,
+        slice: Option<PatternRef<'tcx>>,
+        suffix: Vec<PatternRef<'tcx>>,
+    },
 
     // fixed match against an array, irrefutable
-    Array { prefix: Vec<PatternRef<H>>,
-            slice: Option<PatternRef<H>>,
-            suffix: Vec<PatternRef<H>> },
+    Array {
+        prefix: Vec<PatternRef<'tcx>>,
+        slice: Option<PatternRef<'tcx>>,
+        suffix: Vec<PatternRef<'tcx>>,
+    },
 }
 
 #[derive(Copy, Clone, Debug)]
-pub enum BindingMode<H:Hair> {
+pub enum BindingMode {
     ByValue,
-    ByRef(H::Region, BorrowKind),
+    ByRef(Region, BorrowKind),
 }
 
 #[derive(Clone, Debug)]
-pub enum PatternRef<H:Hair> {
-    Hair(H::Pattern),
-    Mirror(Box<Pattern<H>>),
+pub enum PatternRef<'tcx> {
+    Hair(PatNode<'tcx>),
+    Mirror(Box<Pattern<'tcx>>),
 }
 
 #[derive(Clone, Debug)]
-pub struct FieldPatternRef<H:Hair> {
-    pub field: Field<H>,
-    pub pattern: PatternRef<H>,
+pub struct FieldPatternRef<'tcx> {
+    pub field: Field,
+    pub pattern: PatternRef<'tcx>,
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // The Mirror trait
 
-/// "Mirroring" is the process of converting from a Hair type into one
-/// of the types in this file. For example, the mirror of a `H::Expr`
-/// is an `Expr<H>`. Mirroring is the point at which the actual IR is
-/// converting into the more idealized representation described in
-/// this file. Mirroring is gradual: when you mirror an outer
-/// expression like `e1 + e2`, the references to the inner expressions
-/// `e1` and `e2` are `ExprRef<H>` instances, and they may or may not
-/// be eagerly mirrored.  This allows a single AST node from the
-/// compiler to expand into one or more Hair nodes, which lets the Hair
-/// nodes be simpler.
-pub trait Mirror<H:Hair> {
+/// "Mirroring" is the process of converting from a HIR type into one
+/// of the HAIR types defined in this file. This is basically a "on
+/// the fly" desugaring step that hides a lot of the messiness in the
+/// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
+/// `Expr<'tcx>`.
+///
+/// Mirroring is gradual: when you mirror an outer expression like `e1
+/// + e2`, the references to the inner expressions `e1` and `e2` are
+/// `ExprRef<'tcx>` instances, and they may or may not be eagerly
+/// mirrored.  This allows a single AST node from the compiler to
+/// expand into one or more Hair nodes, which lets the Hair nodes be
+/// simpler.
+pub trait Mirror<'tcx> {
     type Output;
 
-    fn make_mirror(self, hir: &mut H) -> Self::Output;
+    fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Self::Output;
 }
 
-impl<H:Hair> Mirror<H> for Expr<H> {
-    type Output = Expr<H>;
+impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
+    type Output = Expr<'tcx>;
 
-    fn make_mirror(self, _: &mut H) -> Expr<H> {
+    fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
         self
     }
 }
 
-impl<H:Hair> Mirror<H> for ExprRef<H> {
-    type Output = Expr<H>;
+impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
+    type Output = Expr<'tcx>;
 
-    fn make_mirror(self, hir: &mut H) -> Expr<H> {
+    fn make_mirror<'a>(self, hir: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
         match self {
             ExprRef::Hair(h) => h.make_mirror(hir),
             ExprRef::Mirror(m) => *m,
@@ -334,18 +381,18 @@ impl<H:Hair> Mirror<H> for ExprRef<H> {
     }
 }
 
-impl<H:Hair> Mirror<H> for Stmt<H> {
-    type Output = Stmt<H>;
+impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
+    type Output = Stmt<'tcx>;
 
-    fn make_mirror(self, _: &mut H) -> Stmt<H> {
+    fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Stmt<'tcx> {
         self
     }
 }
 
-impl<H:Hair> Mirror<H> for StmtRef<H> {
-    type Output = Stmt<H>;
+impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
+    type Output = Stmt<'tcx>;
 
-    fn make_mirror(self, hir: &mut H) -> Stmt<H> {
+    fn make_mirror<'a>(self, hir: &mut Cx<'a, 'tcx>) -> Stmt<'tcx> {
         match self {
             StmtRef::Hair(h) => h.make_mirror(hir),
             StmtRef::Mirror(m) => *m,
@@ -353,18 +400,18 @@ impl<H:Hair> Mirror<H> for StmtRef<H> {
     }
 }
 
-impl<H:Hair> Mirror<H> for Pattern<H> {
-    type Output = Pattern<H>;
+impl<'tcx> Mirror<'tcx> for Pattern<'tcx> {
+    type Output = Pattern<'tcx>;
 
-    fn make_mirror(self, _: &mut H) -> Pattern<H> {
+    fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Pattern<'tcx> {
         self
     }
 }
 
-impl<H:Hair> Mirror<H> for PatternRef<H> {
-    type Output = Pattern<H>;
+impl<'tcx> Mirror<'tcx> for PatternRef<'tcx> {
+    type Output = Pattern<'tcx>;
 
-    fn make_mirror(self, hir: &mut H) -> Pattern<H> {
+    fn make_mirror<'a>(self, hir: &mut Cx<'a, 'tcx>) -> Pattern<'tcx> {
         match self {
             PatternRef::Hair(h) => h.make_mirror(hir),
             PatternRef::Mirror(m) => *m,
@@ -372,11 +419,10 @@ impl<H:Hair> Mirror<H> for PatternRef<H> {
     }
 }
 
-impl<H:Hair> Mirror<H> for Block<H> {
-    type Output = Block<H>;
+impl<'tcx> Mirror<'tcx> for Block<'tcx> {
+    type Output = Block<'tcx>;
 
-    fn make_mirror(self, _: &mut H) -> Block<H> {
+    fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Block<'tcx> {
         self
     }
 }
-
index ebec1609959ddb3d1f5f9beba14d39f72bd5a880..934dd660177b82c9d06ad4fdbe0eab02f7149c6d 100644 (file)
@@ -18,16 +18,19 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![crate_type = "rlib"]
 #![crate_type = "dylib"]
 
-#![feature(ref_slice)]
 #![feature(rustc_private)]
 #![feature(into_cow)]
 
 #[macro_use] extern crate log;
 extern crate graphviz as dot;
+extern crate rustc;
 extern crate rustc_data_structures;
+extern crate rustc_front;
+extern crate rustc_back;
+extern crate syntax;
 
 pub mod build;
-pub mod dump;
+pub mod mir_map;
 pub mod hair;
 pub mod repr;
 mod graphviz;
diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs
new file mode 100644 (file)
index 0000000..1acbc8d
--- /dev/null
@@ -0,0 +1,241 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! An experimental pass that scources for `#[rustc_mir]` attributes,
+//! builds the resulting MIR, and dumps it out into a file for inspection.
+//!
+//! The attribute formats that are currently accepted are:
+//!
+//! - `#[rustc_mir(graphviz="file.gv")]`
+//! - `#[rustc_mir(pretty="file.mir")]`
+
+extern crate syntax;
+extern crate rustc;
+extern crate rustc_front;
+
+use build;
+use dot;
+use repr::Mir;
+use std::fs::File;
+use tcx::{PatNode, Cx};
+
+use self::rustc::middle::infer;
+use self::rustc::middle::region::CodeExtentData;
+use self::rustc::middle::ty::{self, Ty};
+use self::rustc::util::common::ErrorReported;
+use self::rustc::util::nodemap::NodeMap;
+use self::rustc_front::hir;
+use self::rustc_front::visit;
+use self::syntax::ast;
+use self::syntax::attr::AttrMetaMethods;
+use self::syntax::codemap::Span;
+
+pub type MirMap<'tcx> = NodeMap<Mir<'tcx>>;
+
+pub fn build_mir_for_crate<'tcx>(tcx: &ty::ctxt<'tcx>) -> MirMap<'tcx> {
+    let mut map = NodeMap();
+    {
+        let mut dump = OuterDump {
+            tcx: tcx,
+            map: &mut map,
+        };
+        visit::walk_crate(&mut dump, tcx.map.krate());
+    }
+    map
+}
+
+///////////////////////////////////////////////////////////////////////////
+// OuterDump -- walks a crate, looking for fn items and methods to build MIR from
+
+struct OuterDump<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+    map: &'a mut MirMap<'tcx>,
+}
+
+impl<'a, 'tcx> OuterDump<'a, 'tcx> {
+    fn visit_mir<OP>(&mut self, attributes: &'a [ast::Attribute], mut walk_op: OP)
+        where OP: for<'m> FnMut(&mut InnerDump<'a, 'm, 'tcx>)
+    {
+        let mut closure_dump = InnerDump {
+            tcx: self.tcx,
+            attr: None,
+            map: &mut *self.map,
+        };
+        for attr in attributes {
+            if attr.check_name("rustc_mir") {
+                closure_dump.attr = Some(attr);
+            }
+        }
+        walk_op(&mut closure_dump);
+    }
+}
+
+
+impl<'a, 'tcx> visit::Visitor<'tcx> for OuterDump<'a, 'tcx> {
+    fn visit_item(&mut self, item: &'tcx hir::Item) {
+        self.visit_mir(&item.attrs, |c| visit::walk_item(c, item));
+        visit::walk_item(self, item);
+    }
+
+    fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
+        match trait_item.node {
+            hir::MethodTraitItem(_, Some(_)) => {
+                self.visit_mir(&trait_item.attrs, |c| visit::walk_trait_item(c, trait_item));
+            }
+            hir::MethodTraitItem(_, None) |
+            hir::ConstTraitItem(..) |
+            hir::TypeTraitItem(..) => {}
+        }
+        visit::walk_trait_item(self, trait_item);
+    }
+
+    fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
+        match impl_item.node {
+            hir::MethodImplItem(..) => {
+                self.visit_mir(&impl_item.attrs, |c| visit::walk_impl_item(c, impl_item));
+            }
+            hir::ConstImplItem(..) | hir::TypeImplItem(..) => {}
+        }
+        visit::walk_impl_item(self, impl_item);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// InnerDump -- dumps MIR for a single fn and its contained closures
+
+struct InnerDump<'a, 'm, 'tcx: 'a + 'm> {
+    tcx: &'a ty::ctxt<'tcx>,
+    map: &'m mut MirMap<'tcx>,
+    attr: Option<&'a ast::Attribute>,
+}
+
+impl<'a, 'm, 'tcx> visit::Visitor<'tcx> for InnerDump<'a,'m,'tcx> {
+    fn visit_item(&mut self, _: &'tcx hir::Item) {
+        // ignore nested items; they need their own graphviz annotation
+    }
+
+    fn visit_trait_item(&mut self, _: &'tcx hir::TraitItem) {
+        // ignore nested items; they need their own graphviz annotation
+    }
+
+    fn visit_impl_item(&mut self, _: &'tcx hir::ImplItem) {
+        // ignore nested items; they need their own graphviz annotation
+    }
+
+    fn visit_fn(&mut self,
+                fk: visit::FnKind<'tcx>,
+                decl: &'tcx hir::FnDecl,
+                body: &'tcx hir::Block,
+                span: Span,
+                id: ast::NodeId) {
+        let (prefix, implicit_arg_tys) = match fk {
+            visit::FnKind::Closure =>
+                (format!("{}-", id), vec![closure_self_ty(&self.tcx, id, body.id)]),
+            _ =>
+                (format!(""), vec![]),
+        };
+
+        let param_env = ty::ParameterEnvironment::for_item(self.tcx, id);
+
+        let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, Some(param_env), true);
+
+        match build_mir(Cx::new(&infcx), implicit_arg_tys, id, span, decl, body) {
+            Ok(mir) => {
+                let meta_item_list = self.attr
+                                         .iter()
+                                         .flat_map(|a| a.meta_item_list())
+                                         .flat_map(|l| l.iter());
+                for item in meta_item_list {
+                    if item.check_name("graphviz") {
+                        match item.value_str() {
+                            Some(s) => {
+                                match
+                                    File::create(format!("{}{}", prefix, s))
+                                    .and_then(|ref mut output| dot::render(&mir, output))
+                                {
+                                    Ok(()) => { }
+                                    Err(e) => {
+                                        self.tcx.sess.span_fatal(
+                                            item.span,
+                                            &format!("Error writing graphviz \
+                                                      results to `{}`: {}",
+                                                     s, e));
+                                    }
+                                }
+                            }
+                            None => {
+                                self.tcx.sess.span_err(
+                                    item.span,
+                                    &format!("graphviz attribute requires a path"));
+                            }
+                        }
+                    }
+                }
+
+                let previous = self.map.insert(id, mir);
+                assert!(previous.is_none());
+            }
+            Err(ErrorReported) => {}
+        }
+
+        visit::walk_fn(self, fk, decl, body, span);
+    }
+}
+
+fn build_mir<'a, 'tcx: 'a>(cx: Cx<'a, 'tcx>,
+                           implicit_arg_tys: Vec<Ty<'tcx>>,
+                           fn_id: ast::NodeId,
+                           span: Span,
+                           decl: &'tcx hir::FnDecl,
+                           body: &'tcx hir::Block)
+                           -> Result<Mir<'tcx>, ErrorReported> {
+    let arguments = decl.inputs
+                        .iter()
+                        .map(|arg| {
+                            let ty = cx.tcx().node_id_to_type(arg.id);
+                            (ty, PatNode::irrefutable(&arg.pat))
+                        })
+                        .collect();
+
+    let parameter_scope = cx.tcx().region_maps.lookup_code_extent(CodeExtentData::ParameterScope {
+        fn_id: fn_id,
+        body_id: body.id,
+    });
+    Ok(build::construct(cx, span, implicit_arg_tys, arguments, parameter_scope, body))
+}
+
+fn closure_self_ty<'a, 'tcx>(tcx: &ty::ctxt<'tcx>,
+                             closure_expr_id: ast::NodeId,
+                             body_id: ast::NodeId)
+                             -> Ty<'tcx> {
+    let closure_ty = tcx.node_id_to_type(closure_expr_id);
+
+    // We're just hard-coding the idea that the signature will be
+    // &self or &mut self and hence will have a bound region with
+    // number 0, hokey.
+    let region = ty::Region::ReFree(ty::FreeRegion {
+        scope: tcx.region_maps.item_extent(body_id),
+        bound_region: ty::BoundRegion::BrAnon(0),
+    });
+    let region = tcx.mk_region(region);
+
+    match tcx.closure_kind(tcx.map.local_def_id(closure_expr_id)) {
+        ty::ClosureKind::FnClosureKind =>
+            tcx.mk_ref(region,
+                       ty::TypeAndMut { ty: closure_ty,
+                                        mutbl: hir::MutImmutable }),
+        ty::ClosureKind::FnMutClosureKind =>
+            tcx.mk_ref(region,
+                       ty::TypeAndMut { ty: closure_ty,
+                                        mutbl: hir::MutMutable }),
+        ty::ClosureKind::FnOnceClosureKind =>
+            closure_ty
+    }
+}
index a54942144c5ec8494dc18b23eb0f0169a1e31241..5059955c5dc33d3e13fba308aa0cef3f6198d8d5 100644 (file)
@@ -8,22 +8,29 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use hair::Hair;
+use rustc::middle::const_eval::ConstVal;
+use rustc::middle::def_id::DefId;
+use rustc::middle::region::CodeExtent;
+use rustc::middle::subst::Substs;
+use rustc::middle::ty::{AdtDef, ClosureSubsts, Region, Ty};
+use rustc_back::slice;
 use rustc_data_structures::fnv::FnvHashMap;
+use rustc_front::hir::InlineAsm;
+use syntax::ast::Name;
+use syntax::codemap::Span;
 use std::fmt::{Debug, Formatter, Error};
-use std::slice;
 use std::u32;
 
 /// Lowered representation of a single function.
-pub struct Mir<H:Hair> {
-    pub basic_blocks: Vec<BasicBlockData<H>>,
+pub struct Mir<'tcx> {
+    pub basic_blocks: Vec<BasicBlockData<'tcx>>,
 
     // for every node id
-    pub extents: FnvHashMap<H::CodeExtent, Vec<GraphExtent>>,
+    pub extents: FnvHashMap<CodeExtent, Vec<GraphExtent>>,
 
-    pub var_decls: Vec<VarDecl<H>>,
-    pub arg_decls: Vec<ArgDecl<H>>,
-    pub temp_decls: Vec<TempDecl<H>>,
+    pub var_decls: Vec<VarDecl<'tcx>>,
+    pub arg_decls: Vec<ArgDecl<'tcx>>,
+    pub temp_decls: Vec<TempDecl<'tcx>>,
 }
 
 /// where execution begins
@@ -35,18 +42,18 @@ pub const END_BLOCK: BasicBlock = BasicBlock(1);
 /// where execution ends, on panic
 pub const DIVERGE_BLOCK: BasicBlock = BasicBlock(2);
 
-impl<H:Hair> Mir<H> {
+impl<'tcx> Mir<'tcx> {
     pub fn all_basic_blocks(&self) -> Vec<BasicBlock> {
         (0..self.basic_blocks.len())
             .map(|i| BasicBlock::new(i))
             .collect()
     }
 
-    pub fn basic_block_data(&self, bb: BasicBlock) -> &BasicBlockData<H> {
+    pub fn basic_block_data(&self, bb: BasicBlock) -> &BasicBlockData<'tcx> {
         &self.basic_blocks[bb.index()]
     }
 
-    pub fn basic_block_data_mut(&mut self, bb: BasicBlock) -> &mut BasicBlockData<H> {
+    pub fn basic_block_data_mut(&mut self, bb: BasicBlock) -> &mut BasicBlockData<'tcx> {
         &mut self.basic_blocks[bb.index()]
     }
 }
@@ -103,7 +110,7 @@ pub enum BorrowKind {
     Unique,
 
     /// Data is mutable and not aliasable.
-    Mut
+    Mut,
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -111,16 +118,16 @@ pub enum BorrowKind {
 
 // A "variable" is a binding declared by the user as part of the fn
 // decl, a let, etc.
-pub struct VarDecl<H:Hair> {
+pub struct VarDecl<'tcx> {
     pub mutability: Mutability,
-    pub name: H::Ident,
-    pub ty: H::Ty,
+    pub name: Name,
+    pub ty: Ty<'tcx>,
 }
 
 // A "temp" is a temporary that we place on the stack. They are
 // anonymous, always mutable, and have only a type.
-pub struct TempDecl<H:Hair> {
-    pub ty: H::Ty,
+pub struct TempDecl<'tcx> {
+    pub ty: Ty<'tcx>,
 }
 
 // A "arg" is one of the function's formal arguments. These are
@@ -134,8 +141,8 @@ pub struct TempDecl<H:Hair> {
 //
 // there is only one argument, of type `(i32, u32)`, but two bindings
 // (`x` and `y`).
-pub struct ArgDecl<H:Hair> {
-    pub ty: H::Ty,
+pub struct ArgDecl<'tcx> {
+    pub ty: Ty<'tcx>,
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -212,24 +219,34 @@ impl Debug for BasicBlock {
 // BasicBlock and Terminator
 
 #[derive(Debug)]
-pub struct BasicBlockData<H:Hair> {
-    pub statements: Vec<Statement<H>>,
-    pub terminator: Terminator<H>,
+pub struct BasicBlockData<'tcx> {
+    pub statements: Vec<Statement<'tcx>>,
+    pub terminator: Terminator<'tcx>,
 }
 
-pub enum Terminator<H:Hair> {
+pub enum Terminator<'tcx> {
     /// block should have one successor in the graph; we jump there
-    Goto { target: BasicBlock },
+    Goto {
+        target: BasicBlock,
+    },
 
     /// block should initiate unwinding; should be one successor
     /// that does cleanup and branches to DIVERGE_BLOCK
-    Panic { target: BasicBlock },
+    Panic {
+        target: BasicBlock,
+    },
 
     /// jump to branch 0 if this lvalue evaluates to true
-    If { cond: Operand<H>, targets: [BasicBlock; 2] },
+    If {
+        cond: Operand<'tcx>,
+        targets: [BasicBlock; 2],
+    },
 
     /// lvalue evaluates to some enum; jump depending on the branch
-    Switch { discr: Lvalue<H>, targets: Vec<BasicBlock> },
+    Switch {
+        discr: Lvalue<'tcx>,
+        targets: Vec<BasicBlock>,
+    },
 
     /// Indicates that the last statement in the block panics, aborts,
     /// etc. No successors. This terminator appears on exactly one
@@ -247,10 +264,13 @@ pub enum Terminator<H:Hair> {
     /// block ends with a call; it should have two successors. The
     /// first successor indicates normal return. The second indicates
     /// unwinding.
-    Call { data: CallData<H>, targets: [BasicBlock; 2] },
+    Call {
+        data: CallData<'tcx>,
+        targets: [BasicBlock; 2],
+    },
 }
 
-impl<H:Hair> Terminator<H> {
+impl<'tcx> Terminator<'tcx> {
     pub fn successors(&self) -> &[BasicBlock] {
         use self::Terminator::*;
         match *self {
@@ -266,19 +286,19 @@ impl<H:Hair> Terminator<H> {
 }
 
 #[derive(Debug)]
-pub struct CallData<H:Hair> {
+pub struct CallData<'tcx> {
     /// where the return value is written to
-    pub destination: Lvalue<H>,
+    pub destination: Lvalue<'tcx>,
 
     /// the fn being called
-    pub func: Lvalue<H>,
+    pub func: Lvalue<'tcx>,
 
     /// the arguments
-    pub args: Vec<Lvalue<H>>,
+    pub args: Vec<Lvalue<'tcx>>,
 }
 
-impl<H:Hair> BasicBlockData<H> {
-    pub fn new(terminator: Terminator<H>) -> BasicBlockData<H> {
+impl<'tcx> BasicBlockData<'tcx> {
+    pub fn new(terminator: Terminator<'tcx>) -> BasicBlockData<'tcx> {
         BasicBlockData {
             statements: vec![],
             terminator: terminator,
@@ -286,7 +306,7 @@ impl<H:Hair> BasicBlockData<H> {
     }
 }
 
-impl<H:Hair> Debug for Terminator<H> {
+impl<'tcx> Debug for Terminator<'tcx> {
     fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
         use self::Terminator::*;
         match *self {
@@ -305,7 +325,9 @@ impl<H:Hair> Debug for Terminator<H> {
             Call { data: ref c, targets } => {
                 try!(write!(fmt, "{:?} = {:?}(", c.destination, c.func));
                 for (index, arg) in c.args.iter().enumerate() {
-                    if index > 0 { try!(write!(fmt, ", ")); }
+                    if index > 0 {
+                        try!(write!(fmt, ", "));
+                    }
                     try!(write!(fmt, "{:?}", arg));
                 }
                 write!(fmt, ") -> {:?}", targets)
@@ -318,24 +340,24 @@ impl<H:Hair> Debug for Terminator<H> {
 ///////////////////////////////////////////////////////////////////////////
 // Statements
 
-pub struct Statement<H:Hair> {
-    pub span: H::Span,
-    pub kind: StatementKind<H>,
+pub struct Statement<'tcx> {
+    pub span: Span,
+    pub kind: StatementKind<'tcx>,
 }
 
 #[derive(Debug)]
-pub enum StatementKind<H:Hair> {
-    Assign(Lvalue<H>, Rvalue<H>),
-    Drop(DropKind, Lvalue<H>),
+pub enum StatementKind<'tcx> {
+    Assign(Lvalue<'tcx>, Rvalue<'tcx>),
+    Drop(DropKind, Lvalue<'tcx>),
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub enum DropKind {
     Shallow,
-    Deep
+    Deep,
 }
 
-impl<H:Hair> Debug for Statement<H> {
+impl<'tcx> Debug for Statement<'tcx> {
     fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
         use self::StatementKind::*;
         match self.kind {
@@ -351,7 +373,7 @@ impl<H:Hair> Debug for Statement<H> {
 /// A path to a value; something that can be evaluated without
 /// changing or disturbing program state.
 #[derive(Clone, PartialEq)]
-pub enum Lvalue<H:Hair> {
+pub enum Lvalue<'tcx> {
     /// local variable declared by the user
     Var(u32),
 
@@ -363,13 +385,13 @@ pub enum Lvalue<H:Hair> {
     Arg(u32),
 
     /// static or static mut variable
-    Static(H::DefId),
+    Static(DefId),
 
     /// the return pointer of the fn
     ReturnPointer,
 
     /// projection out of an lvalue (access a field, deref a pointer, etc)
-    Projection(Box<LvalueProjection<H>>)
+    Projection(Box<LvalueProjection<'tcx>>),
 }
 
 /// The `Projection` data structure defines things of the form `B.x`
@@ -377,15 +399,15 @@ pub enum Lvalue<H:Hair> {
 /// shared between `Constant` and `Lvalue`. See the aliases
 /// `LvalueProjection` etc below.
 #[derive(Clone, Debug, PartialEq)]
-pub struct Projection<H:Hair,B,V> {
+pub struct Projection<'tcx, B, V> {
     pub base: B,
-    pub elem: ProjectionElem<H,V>,
+    pub elem: ProjectionElem<'tcx, V>,
 }
 
 #[derive(Clone, Debug, PartialEq)]
-pub enum ProjectionElem<H:Hair,V> {
+pub enum ProjectionElem<'tcx, V> {
     Deref,
-    Field(Field<H>),
+    Field(Field),
     Index(V),
 
     // These indices are generated by slice patterns. Easiest to explain
@@ -406,44 +428,47 @@ pub enum ProjectionElem<H:Hair,V> {
     // "Downcast" to a variant of an ADT. Currently, we only introduce
     // this for ADTs with more than one variant. It may be better to
     // just introduce it always, or always for enums.
-    Downcast(H::AdtDef, usize),
+    Downcast(AdtDef<'tcx>, usize),
 }
 
 /// Alias for projections as they appear in lvalues, where the base is an lvalue
 /// and the index is an operand.
-pub type LvalueProjection<H> =
-    Projection<H,Lvalue<H>,Operand<H>>;
+pub type LvalueProjection<'tcx> =
+    Projection<'tcx,Lvalue<'tcx>,Operand<'tcx>>;
 
 /// Alias for projections as they appear in lvalues, where the base is an lvalue
 /// and the index is an operand.
-pub type LvalueElem<H> =
-    ProjectionElem<H,Operand<H>>;
+pub type LvalueElem<'tcx> =
+    ProjectionElem<'tcx,Operand<'tcx>>;
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub enum Field<H:Hair> {
-    Named(H::Name),
+pub enum Field {
+    Named(Name),
     Indexed(usize),
 }
 
-impl<H:Hair> Lvalue<H> {
-    pub fn field(self, f: Field<H>) -> Lvalue<H> {
+impl<'tcx> Lvalue<'tcx> {
+    pub fn field(self, f: Field) -> Lvalue<'tcx> {
         self.elem(ProjectionElem::Field(f))
     }
 
-    pub fn deref(self) -> Lvalue<H> {
+    pub fn deref(self) -> Lvalue<'tcx> {
         self.elem(ProjectionElem::Deref)
     }
 
-    pub fn index(self, index: Operand<H>) -> Lvalue<H> {
+    pub fn index(self, index: Operand<'tcx>) -> Lvalue<'tcx> {
         self.elem(ProjectionElem::Index(index))
     }
 
-    pub fn elem(self, elem: LvalueElem<H>) -> Lvalue<H> {
-        Lvalue::Projection(Box::new(LvalueProjection { base: self, elem: elem }))
+    pub fn elem(self, elem: LvalueElem<'tcx>) -> Lvalue<'tcx> {
+        Lvalue::Projection(Box::new(LvalueProjection {
+            base: self,
+            elem: elem,
+        }))
     }
 }
 
-impl<H:Hair> Debug for Lvalue<H> {
+impl<'tcx> Debug for Lvalue<'tcx> {
     fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
         use self::Lvalue::*;
 
@@ -487,12 +512,12 @@ impl<H:Hair> Debug for Lvalue<H> {
 // being nested in one another.
 
 #[derive(Clone, PartialEq)]
-pub enum Operand<H:Hair> {
-    Consume(Lvalue<H>),
-    Constant(Constant<H>),
+pub enum Operand<'tcx> {
+    Consume(Lvalue<'tcx>),
+    Constant(Constant<'tcx>),
 }
 
-impl<H:Hair> Debug for Operand<H> {
+impl<'tcx> Debug for Operand<'tcx> {
     fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
         use self::Operand::*;
         match *self {
@@ -506,34 +531,34 @@ impl<H:Hair> Debug for Operand<H> {
 // Rvalues
 
 #[derive(Clone)]
-pub enum Rvalue<H:Hair> {
+pub enum Rvalue<'tcx> {
     // x (either a move or copy, depending on type of x)
-    Use(Operand<H>),
+    Use(Operand<'tcx>),
 
     // [x; 32]
-    Repeat(Operand<H>, Operand<H>),
+    Repeat(Operand<'tcx>, Operand<'tcx>),
 
     // &x or &mut x
-    Ref(H::Region, BorrowKind, Lvalue<H>),
+    Ref(Region, BorrowKind, Lvalue<'tcx>),
 
     // length of a [X] or [X;n] value
-    Len(Lvalue<H>),
+    Len(Lvalue<'tcx>),
 
-    Cast(CastKind, Operand<H>, H::Ty),
+    Cast(CastKind, Operand<'tcx>, Ty<'tcx>),
 
-    BinaryOp(BinOp, Operand<H>, Operand<H>),
+    BinaryOp(BinOp, Operand<'tcx>, Operand<'tcx>),
 
-    UnaryOp(UnOp, Operand<H>),
+    UnaryOp(UnOp, Operand<'tcx>),
 
     // Creates an *uninitialized* Box
-    Box(H::Ty),
+    Box(Ty<'tcx>),
 
     // Create an aggregate value, like a tuple or struct.  This is
     // only needed because we want to distinguish `dest = Foo { x:
     // ..., y: ... }` from `dest.x = ...; dest.y = ...;` in the case
     // that `Foo` has a destructor. These rvalues can be optimized
     // away after type-checking and before lowering.
-    Aggregate(AggregateKind<H>, Vec<Operand<H>>),
+    Aggregate(AggregateKind<'tcx>, Vec<Operand<'tcx>>),
 
     // Generates a slice of the form `&input[from_start..L-from_end]`
     // where `L` is the length of the slice. This is only created by
@@ -541,12 +566,12 @@ pub enum Rvalue<H:Hair> {
     // .., z]` might create a slice with `from_start=2` and
     // `from_end=1`.
     Slice {
-        input: Lvalue<H>,
+        input: Lvalue<'tcx>,
         from_start: usize,
         from_end: usize,
     },
 
-    InlineAsm(H::InlineAsm),
+    InlineAsm(&'tcx InlineAsm),
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -568,11 +593,11 @@ pub enum CastKind {
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
-pub enum AggregateKind<H:Hair> {
+pub enum AggregateKind<'tcx> {
     Vec,
     Tuple,
-    Adt(H::AdtDef, usize, H::Substs),
-    Closure(H::DefId, H::ClosureSubsts),
+    Adt(AdtDef<'tcx>, usize, &'tcx Substs<'tcx>),
+    Closure(DefId, &'tcx ClosureSubsts<'tcx>),
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -616,10 +641,10 @@ pub enum UnOp {
     /// The `!` operator for logical inversion
     Not,
     /// The `-` operator for negation
-    Neg
+    Neg,
 }
 
-impl<H:Hair> Debug for Rvalue<H> {
+impl<'tcx> Debug for Rvalue<'tcx> {
     fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
         use self::Rvalue::*;
 
@@ -634,56 +659,33 @@ impl<H:Hair> Debug for Rvalue<H> {
             Box(ref t) => write!(fmt, "Box {:?}", t),
             Aggregate(ref kind, ref lvs) => write!(fmt, "Aggregate<{:?}>({:?})", kind, lvs),
             InlineAsm(ref asm) => write!(fmt, "InlineAsm({:?})", asm),
-            Slice { ref input, from_start, from_end } => write!(fmt, "{:?}[{:?}..-{:?}]",
-                                                                input, from_start, from_end),
+            Slice { ref input, from_start, from_end } =>
+                write!(fmt, "{:?}[{:?}..-{:?}]", input, from_start, from_end),
         }
     }
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // Constants
+//
+// Two constants are equal if they are the same constant. Note that
+// this does not necessarily mean that they are "==" in Rust -- in
+// particular one must be wary of `NaN`!
 
 #[derive(Clone, Debug, PartialEq)]
-pub struct Constant<H:Hair> {
-    pub span: H::Span,
-    pub kind: ConstantKind<H>
-}
-
-#[derive(Clone, Debug, PartialEq)]
-pub enum ConstantKind<H:Hair> {
-    Literal(Literal<H>),
-    Aggregate(AggregateKind<H>, Vec<Constant<H>>),
-    Call(Box<Constant<H>>, Vec<Constant<H>>),
-    Cast(Box<Constant<H>>, H::Ty),
-    Repeat(Box<Constant<H>>, Box<Constant<H>>),
-    Ref(BorrowKind, Box<Constant<H>>),
-    BinaryOp(BinOp, Box<Constant<H>>, Box<Constant<H>>),
-    UnaryOp(UnOp, Box<Constant<H>>),
-    Projection(Box<ConstantProjection<H>>)
+pub struct Constant<'tcx> {
+    pub span: Span,
+    pub ty: Ty<'tcx>,
+    pub literal: Literal<'tcx>,
 }
 
-pub type ConstantProjection<H> =
-    Projection<H,Constant<H>,Constant<H>>;
-
 #[derive(Clone, Debug, PartialEq)]
-pub enum Literal<H:Hair> {
-    Item { def_id: H::DefId, substs: H::Substs },
-    Projection { projection: H::Projection },
-    Int { bits: IntegralBits, value: i64 },
-    Uint { bits: IntegralBits, value: u64 },
-    Float { bits: FloatBits, value: f64 },
-    Char { c: char },
-    Bool { value: bool },
-    Bytes { value: H::Bytes },
-    String { value: H::InternedString },
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
-pub enum IntegralBits {
-    B8, B16, B32, B64, BSize
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
-pub enum FloatBits {
-    F32, F64
+pub enum Literal<'tcx> {
+    Item {
+        def_id: DefId,
+        substs: &'tcx Substs<'tcx>,
+    },
+    Value {
+        value: ConstVal,
+    },
 }
index 033e6ed2968b6226ea436fb2600a466d7e84ab13..dc168bc7c2b6cad8ad15a45a8bd6263e062b58cf 100644 (file)
@@ -12,16 +12,16 @@ use hair::*;
 
 use tcx::Cx;
 use tcx::pattern::PatNode;
-use tcx::rustc::middle::region::{BlockRemainder, CodeExtentData};
-use tcx::rustc_front::hir;
-use tcx::syntax::ast;
-use tcx::syntax::ptr::P;
 use tcx::to_ref::ToRef;
+use rustc::middle::region::{BlockRemainder, CodeExtentData};
+use rustc_front::hir;
+use syntax::ast;
+use syntax::ptr::P;
 
-impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Block {
-    type Output = Block<Cx<'a,'tcx>>;
+impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
+    type Output = Block<'tcx>;
 
-    fn make_mirror(self, cx: &mut Cx<'a,'tcx>) -> Block<Cx<'a,'tcx>> {
+    fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Block<'tcx> {
         // We have to eagerly translate the "spine" of the statements
         // in order to get the lexical scoping correctly.
         let stmts = mirror_stmts(cx, self.id, self.stmts.iter().enumerate());
@@ -29,15 +29,15 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Block {
             extent: cx.tcx.region_maps.node_extent(self.id),
             span: self.span,
             stmts: stmts,
-            expr: self.expr.to_ref()
+            expr: self.expr.to_ref(),
         }
     }
 }
 
-impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Stmt {
-    type Output = Stmt<Cx<'a,'tcx>>;
+impl<'tcx> Mirror<'tcx> for &'tcx hir::Stmt {
+    type Output = Stmt<'tcx>;
 
-    fn make_mirror(self, _cx: &mut Cx<'a,'tcx>) -> Stmt<Cx<'a,'tcx>> {
+    fn make_mirror<'a>(self, _cx: &mut Cx<'a, 'tcx>) -> Stmt<'tcx> {
         // In order to get the scoping correct, we eagerly mirror
         // statements when we translate the enclosing block, so we
         // should in fact never get to this point.
@@ -45,11 +45,11 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Stmt {
     }
 }
 
-fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>,
-                                  block_id: ast::NodeId,
-                                  mut stmts: STMTS)
-                                  -> Vec<StmtRef<Cx<'a,'tcx>>>
-    where STMTS: Iterator<Item=(usize, &'tcx P<hir::Stmt>)>
+fn mirror_stmts<'a, 'tcx: 'a, STMTS>(cx: &mut Cx<'a, 'tcx>,
+                                     block_id: ast::NodeId,
+                                     mut stmts: STMTS)
+                                     -> Vec<StmtRef<'tcx>>
+    where STMTS: Iterator<Item = (usize, &'tcx P<hir::Stmt>)>
 {
     let mut result = vec![];
     while let Some((index, stmt)) = stmts.next() {
@@ -68,7 +68,7 @@ fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>,
                     hir::DeclLocal(ref local) => {
                         let remainder_extent = CodeExtentData::Remainder(BlockRemainder {
                             block: block_id,
-                            first_statement_index: index as u32
+                            first_statement_index: index as u32,
                         });
                         let remainder_extent =
                             cx.tcx.region_maps.lookup_code_extent(remainder_extent);
@@ -77,18 +77,16 @@ fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>,
                         // they are within the scope of this let:
                         let following_stmts = mirror_stmts(cx, block_id, stmts);
 
-                        result.push(
-                            StmtRef::Mirror(
-                                Box::new(Stmt {
-                                    span: stmt.span,
-                                    kind: StmtKind::Let {
-                                        remainder_scope: remainder_extent,
-                                        init_scope: cx.tcx.region_maps.node_extent(id),
-                                        pattern: PatNode::irrefutable(&local.pat).to_ref(),
-                                        initializer: local.init.to_ref(),
-                                        stmts: following_stmts
-                                    }
-                                })));
+                        result.push(StmtRef::Mirror(Box::new(Stmt {
+                            span: stmt.span,
+                            kind: StmtKind::Let {
+                                remainder_scope: remainder_extent,
+                                init_scope: cx.tcx.region_maps.node_extent(id),
+                                pattern: PatNode::irrefutable(&local.pat).to_ref(),
+                                initializer: local.init.to_ref(),
+                                stmts: following_stmts,
+                            },
+                        })));
 
                         return result;
                     }
@@ -99,16 +97,14 @@ fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>,
     return result;
 }
 
-pub fn to_expr_ref<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
-                               block: &'tcx hir::Block)
-                               -> ExprRef<Cx<'a, 'tcx>> {
+pub fn to_expr_ref<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, block: &'tcx hir::Block) -> ExprRef<'tcx> {
     let block_ty = cx.tcx.node_id_to_type(block.id);
     let temp_lifetime = cx.tcx.region_maps.temporary_scope(block.id);
     let expr = Expr {
         ty: block_ty,
         temp_lifetime: temp_lifetime,
         span: block.span,
-        kind: ExprKind::Block { body: block }
+        kind: ExprKind::Block { body: block },
     };
     expr.to_ref()
 }
index f15470e7851d41b133e5470748154e94506888ab..4604ca957d88ea226b72b5e08722ef9ab59100c0 100644 (file)
@@ -15,30 +15,29 @@ use std::rc::Rc;
 use tcx::Cx;
 use tcx::block;
 use tcx::pattern::PatNode;
-use tcx::rustc::front::map;
-use tcx::rustc::middle::def;
-use tcx::rustc::middle::def_id::DefId;
-use tcx::rustc::middle::region::CodeExtent;
-use tcx::rustc::middle::pat_util;
-use tcx::rustc::middle::ty::{self, Ty};
-use tcx::rustc_front::hir;
-use tcx::rustc_front::util as hir_util;
-use tcx::syntax::codemap::Span;
-use tcx::syntax::parse::token;
-use tcx::syntax::ptr::P;
 use tcx::to_ref::ToRef;
-
-impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
-    type Output = Expr<Cx<'a,'tcx>>;
-
-    fn make_mirror(self, cx: &mut Cx<'a,'tcx>) -> Expr<Cx<'a,'tcx>> {
+use rustc::front::map;
+use rustc::middle::const_eval;
+use rustc::middle::def;
+use rustc::middle::region::CodeExtent;
+use rustc::middle::pat_util;
+use rustc::middle::ty::{self, Ty};
+use rustc_front::hir;
+use rustc_front::util as hir_util;
+use syntax::ext::mtwt;
+use syntax::parse::token;
+use syntax::ptr::P;
+
+impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
+    type Output = Expr<'tcx>;
+
+    fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
         debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span);
 
         let expr_ty = cx.tcx.expr_ty(self); // note: no adjustments (yet)!
 
         let kind = match self.node {
             // Here comes the interesting stuff:
-
             hir::ExprMethodCall(_, _, ref args) => {
                 // Rewrite a.b(c) into UFCS form like Trait::b(a, c)
                 let expr = method_callee(cx, self, ty::MethodCall::expr(self.id));
@@ -47,24 +46,24 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
                                .collect();
                 ExprKind::Call {
                     fun: expr.to_ref(),
-                    args: args
+                    args: args,
                 }
             }
 
             hir::ExprAddrOf(mutbl, ref expr) => {
                 let region = match expr_ty.sty {
                     ty::TyRef(r, _) => r,
-                    _ => cx.tcx.sess.span_bug(expr.span, "type of & not region")
+                    _ => cx.tcx.sess.span_bug(expr.span, "type of & not region"),
                 };
-                ExprKind::Borrow { region: *region,
-                                   borrow_kind: to_borrow_kind(mutbl),
-                                   arg: expr.to_ref() }
+                ExprKind::Borrow {
+                    region: *region,
+                    borrow_kind: to_borrow_kind(mutbl),
+                    arg: expr.to_ref(),
+                }
             }
 
             hir::ExprBlock(ref blk) => {
-                ExprKind::Block {
-                    body: &**blk
-                }
+                ExprKind::Block { body: &**blk }
             }
 
             hir::ExprAssign(ref lhs, ref rhs) => {
@@ -83,9 +82,9 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
                 }
             }
 
-            hir::ExprLit(ref lit) => {
-                let literal = convert_literal(cx, self.span, expr_ty, lit);
-                ExprKind::Literal { literal: literal }
+            hir::ExprLit(..) => {
+                let value = const_eval::eval_const_expr(cx.tcx, self);
+                ExprKind::Literal { literal: Literal::Value { value: value } }
             }
 
             hir::ExprBinary(op, ref lhs, ref rhs) => {
@@ -101,20 +100,26 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
                     // FIXME overflow
                     match op.node {
                         hir::BinOp_::BiAnd => {
-                            ExprKind::LogicalOp { op: LogicalOp::And,
-                                                  lhs: lhs.to_ref(),
-                                                  rhs: rhs.to_ref() }
+                            ExprKind::LogicalOp {
+                                op: LogicalOp::And,
+                                lhs: lhs.to_ref(),
+                                rhs: rhs.to_ref(),
+                            }
                         }
                         hir::BinOp_::BiOr => {
-                            ExprKind::LogicalOp { op: LogicalOp::Or,
-                                                  lhs: lhs.to_ref(),
-                                                  rhs: rhs.to_ref() }
+                            ExprKind::LogicalOp {
+                                op: LogicalOp::Or,
+                                lhs: lhs.to_ref(),
+                                rhs: rhs.to_ref(),
+                            }
                         }
                         _ => {
                             let op = bin_op(op.node);
-                            ExprKind::Binary { op: op,
-                                               lhs: lhs.to_ref(),
-                                               rhs: rhs.to_ref() }
+                            ExprKind::Binary {
+                                op: op,
+                                lhs: lhs.to_ref(),
+                                rhs: rhs.to_ref(),
+                            }
                         }
                     }
                 }
@@ -125,8 +130,10 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
                     overloaded_lvalue(cx, self, ty::MethodCall::expr(self.id),
                                       PassArgs::ByValue, lhs.to_ref(), vec![index])
                 } else {
-                    ExprKind::Index { lhs: lhs.to_ref(),
-                                      index: index.to_ref() }
+                    ExprKind::Index {
+                        lhs: lhs.to_ref(),
+                        index: index.to_ref(),
+                    }
                 }
             }
 
@@ -139,11 +146,6 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
                 }
             }
 
-            hir::ExprUnary(hir::UnOp::UnUniq, ref arg) => {
-                assert!(!cx.tcx.is_method_call(self.id));
-                ExprKind::Box { place: None, value: arg.to_ref() }
-            }
-
             hir::ExprUnary(op, ref arg) => {
                 if cx.tcx.is_method_call(self.id) {
                     overloaded_operator(cx, self, ty::MethodCall::expr(self.id),
@@ -153,13 +155,16 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
                     let op = match op {
                         hir::UnOp::UnNot => UnOp::Not,
                         hir::UnOp::UnNeg => UnOp::Neg,
-                        hir::UnOp::UnUniq | hir::UnOp::UnDeref => {
+                        hir::UnOp::UnDeref => {
                             cx.tcx.sess.span_bug(
                                 self.span,
-                                &format!("operator should have been handled elsewhere {:?}", op));
+                                "UnDeref should have been handled elsewhere");
                         }
                     };
-                    ExprKind::Unary { op: op, arg: arg.to_ref() }
+                    ExprKind::Unary {
+                        op: op,
+                        arg: arg.to_ref(),
+                    }
                 }
             }
 
@@ -208,8 +213,8 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
                     ty::TyClosure(def_id, ref substs) => (def_id, substs),
                     _ => {
                         cx.tcx.sess.span_bug(self.span,
-                                          &format!("closure expr w/o closure type: {:?}",
-                                                   closure_ty));
+                                             &format!("closure expr w/o closure type: {:?}",
+                                                      closure_ty));
                     }
                 };
                 let upvars = cx.tcx.with_freevars(self.id, |freevars| {
@@ -230,15 +235,15 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
                 let (adt_def, substs) = match range_ty.sty {
                     ty::TyStruct(adt_def, substs) => (adt_def, substs),
                     _ => {
-                        cx.tcx.sess.span_bug(
-                            self.span,
-                            &format!("unexpanded ast"));
+                        cx.tcx.sess.span_bug(self.span, &format!("unexpanded ast"));
                     }
                 };
 
                 let field_expr_ref = |s: &'tcx P<hir::Expr>, nm: &str| {
-                    FieldExprRef { name: Field::Named(token::intern(nm)),
-                                   expr: s.to_ref() }
+                    FieldExprRef {
+                        name: Field::Named(token::intern(nm)),
+                        expr: s.to_ref(),
+                    }
                 };
 
                 let start_field = start.as_ref()
@@ -249,11 +254,13 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
                                    .into_iter()
                                    .map(|e| field_expr_ref(e, "end"));
 
-                ExprKind::Adt { adt_def: adt_def,
-                                variant_index: 0,
-                                substs: substs,
-                                fields: start_field.chain(end_field).collect(),
-                                base: None }
+                ExprKind::Adt {
+                    adt_def: adt_def,
+                    variant_index: 0,
+                    substs: substs,
+                    fields: start_field.chain(end_field).collect(),
+                    base: None,
+                }
             }
 
             hir::ExprPath(..) => {
@@ -266,8 +273,6 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
 
             // Now comes the rote stuff:
 
-            hir::ExprParen(ref p) =>
-                ExprKind::Paren { arg: p.to_ref() },
             hir::ExprRepeat(ref v, ref c) =>
                 ExprKind::Repeat { value: v.to_ref(), count: c.to_ref() },
             hir::ExprRet(ref v) =>
@@ -289,16 +294,16 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
             hir::ExprLoop(ref body, _) =>
                 ExprKind::Loop { condition: None,
                                  body: block::to_expr_ref(cx, body) },
-            hir::ExprField(ref source, ident) =>
+            hir::ExprField(ref source, name) =>
                 ExprKind::Field { lhs: source.to_ref(),
-                                  name: Field::Named(ident.node.name) },
-            hir::ExprTupField(ref source, ident) =>
+                                  name: Field::Named(name.node) },
+            hir::ExprTupField(ref source, index) =>
                 ExprKind::Field { lhs: source.to_ref(),
-                                  name: Field::Indexed(ident.node) },
+                                  name: Field::Indexed(index.node) },
             hir::ExprCast(ref source, _) =>
                 ExprKind::Cast { source: source.to_ref() },
-            hir::ExprBox(ref place, ref value) =>
-                ExprKind::Box { place: place.to_ref(), value: value.to_ref() },
+            hir::ExprBox(ref value) =>
+                ExprKind::Box { value: value.to_ref() },
             hir::ExprVec(ref fields) =>
                 ExprKind::Vec { fields: fields.to_ref() },
             hir::ExprTup(ref fields) =>
@@ -319,7 +324,7 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
 
         // Now apply adjustments, if any.
         match cx.tcx.tables.borrow().adjustments.get(&self.id) {
-            None => { }
+            None => {}
             Some(&ty::adjustment::AdjustReifyFnPointer) => {
                 let adjusted_ty = cx.tcx.expr_ty_adjusted(self);
                 expr = Expr {
@@ -358,7 +363,7 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
                         temp_lifetime: temp_lifetime,
                         ty: adjusted_ty,
                         span: self.span,
-                        kind: kind
+                        kind: kind,
                     };
                 }
 
@@ -367,7 +372,7 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
                         temp_lifetime: temp_lifetime,
                         ty: target,
                         span: self.span,
-                        kind: ExprKind::Unsize { source: expr.to_ref() }
+                        kind: ExprKind::Unsize { source: expr.to_ref() },
                     };
                 } else if let Some(autoref) = adj.autoref {
                     let adjusted_ty = expr.ty.adjust_for_autoref(cx.tcx, Some(autoref));
@@ -377,9 +382,11 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
                                 temp_lifetime: temp_lifetime,
                                 ty: adjusted_ty,
                                 span: self.span,
-                                kind: ExprKind::Borrow { region: *r,
-                                                         borrow_kind: to_borrow_kind(m),
-                                                         arg: expr.to_ref() }
+                                kind: ExprKind::Borrow {
+                                    region: *r,
+                                    borrow_kind: to_borrow_kind(m),
+                                    arg: expr.to_ref(),
+                                },
                             };
                         }
                         ty::adjustment::AutoUnsafe(m) => {
@@ -392,15 +399,17 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
                                 temp_lifetime: temp_lifetime,
                                 ty: cx.tcx.mk_ref(region, ty::TypeAndMut { ty: expr.ty, mutbl: m }),
                                 span: self.span,
-                                kind: ExprKind::Borrow { region: *region,
-                                                         borrow_kind: to_borrow_kind(m),
-                                                         arg: expr.to_ref() }
+                                kind: ExprKind::Borrow {
+                                    region: *region,
+                                    borrow_kind: to_borrow_kind(m),
+                                    arg: expr.to_ref(),
+                                },
                             };
                             expr = Expr {
                                 temp_lifetime: temp_lifetime,
                                 ty: adjusted_ty,
                                 span: self.span,
-                                kind: ExprKind::Cast { source: expr.to_ref() }
+                                kind: ExprKind::Cast { source: expr.to_ref() },
                             };
                         }
                     }
@@ -413,8 +422,10 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
             temp_lifetime: temp_lifetime,
             ty: expr.ty,
             span: self.span,
-            kind: ExprKind::Scope { extent: expr_extent,
-                                    value: expr.to_ref() }
+            kind: ExprKind::Scope {
+                extent: expr_extent,
+                value: expr.to_ref(),
+            },
         };
 
         // Finally, create a destruction scope, if any.
@@ -423,7 +434,10 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
                 temp_lifetime: temp_lifetime,
                 ty: expr.ty,
                 span: self.span,
-                kind: ExprKind::Scope { extent: extent, value: expr.to_ref() }
+                kind: ExprKind::Scope {
+                    extent: extent,
+                    value: expr.to_ref(),
+                },
             };
         }
 
@@ -432,10 +446,10 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for &'tcx hir::Expr {
     }
 }
 
-fn method_callee<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
-                             expr: &hir::Expr,
-                             method_call: ty::MethodCall)
-                             -> Expr<Cx<'a,'tcx>> {
+fn method_callee<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
+                               expr: &hir::Expr,
+                               method_call: ty::MethodCall)
+                               -> Expr<'tcx> {
     let tables = cx.tcx.tables.borrow();
     let callee = &tables.method_map[&method_call];
     let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
@@ -447,8 +461,8 @@ fn method_callee<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
             literal: Literal::Item {
                 def_id: callee.def_id,
                 substs: callee.substs,
-            }
-        }
+            },
+        },
     }
 }
 
@@ -459,87 +473,25 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind {
     }
 }
 
-fn convert_literal<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
-                               expr_span: Span,
-                               expr_ty: Ty<'tcx>,
-                               literal: &hir::Lit)
-                               -> Literal<Cx<'a,'tcx>>
-{
-    use repr::IntegralBits::*;
-    match (&literal.node, &expr_ty.sty) {
-        (&hir::LitStr(ref text, _), _) =>
-            Literal::String { value: text.clone() },
-        (&hir::LitByteStr(ref bytes), _) =>
-            Literal::Bytes { value: bytes.clone() },
-        (&hir::LitByte(c), _) =>
-            Literal::Uint { bits: B8, value: c as u64 },
-        (&hir::LitChar(c), _) =>
-            Literal::Char { c: c },
-        (&hir::LitInt(v, _), &ty::TyUint(hir::TyU8)) =>
-            Literal::Uint { bits: B8, value: v },
-        (&hir::LitInt(v, _), &ty::TyUint(hir::TyU16)) =>
-            Literal::Uint { bits: B16, value: v },
-        (&hir::LitInt(v, _), &ty::TyUint(hir::TyU32)) =>
-            Literal::Uint { bits: B32, value: v },
-        (&hir::LitInt(v, _), &ty::TyUint(hir::TyU64)) =>
-            Literal::Uint { bits: B64, value: v },
-        (&hir::LitInt(v, _), &ty::TyUint(hir::TyUs)) =>
-            Literal::Uint { bits: BSize, value: v },
-        (&hir::LitInt(v, hir::SignedIntLit(_, hir::Sign::Minus)), &ty::TyInt(hir::TyI8)) =>
-            Literal::Int { bits: B8, value: -(v as i64) },
-        (&hir::LitInt(v, hir::SignedIntLit(_, hir::Sign::Minus)), &ty::TyInt(hir::TyI16)) =>
-            Literal::Int { bits: B16, value: -(v as i64) },
-        (&hir::LitInt(v, hir::SignedIntLit(_, hir::Sign::Minus)), &ty::TyInt(hir::TyI32)) =>
-            Literal::Int { bits: B32, value: -(v as i64) },
-        (&hir::LitInt(v, hir::SignedIntLit(_, hir::Sign::Minus)), &ty::TyInt(hir::TyI64)) =>
-            Literal::Int { bits: B64, value: -(v as i64) },
-        (&hir::LitInt(v, hir::SignedIntLit(_, hir::Sign::Minus)), &ty::TyInt(hir::TyIs)) =>
-            Literal::Int { bits: BSize, value: -(v as i64) },
-        (&hir::LitInt(v, _), &ty::TyInt(hir::TyI8)) =>
-            Literal::Int { bits: B8, value: v as i64 },
-        (&hir::LitInt(v, _), &ty::TyInt(hir::TyI16)) =>
-            Literal::Int { bits: B16, value: v as i64 },
-        (&hir::LitInt(v, _), &ty::TyInt(hir::TyI32)) =>
-            Literal::Int { bits: B32, value: v as i64 },
-        (&hir::LitInt(v, _), &ty::TyInt(hir::TyI64)) =>
-            Literal::Int { bits: B64, value: v as i64 },
-        (&hir::LitInt(v, _), &ty::TyInt(hir::TyIs)) =>
-            Literal::Int { bits: BSize, value: v as i64 },
-        (&hir::LitFloat(ref v, _), &ty::TyFloat(hir::TyF32)) |
-        (&hir::LitFloatUnsuffixed(ref v), &ty::TyFloat(hir::TyF32)) =>
-            Literal::Float { bits: FloatBits::F32, value: v.parse::<f64>().unwrap() },
-        (&hir::LitFloat(ref v, _), &ty::TyFloat(hir::TyF64)) |
-        (&hir::LitFloatUnsuffixed(ref v), &ty::TyFloat(hir::TyF64)) =>
-            Literal::Float { bits: FloatBits::F64, value: v.parse::<f64>().unwrap() },
-        (&hir::LitBool(v), _) =>
-            Literal::Bool { value: v },
-        (ref l, ref t) =>
-            cx.tcx.sess.span_bug(
-                expr_span,
-                &format!("Invalid literal/type combination: {:?},{:?}", l, t))
-    }
-}
-
-fn convert_arm<'a,'tcx:'a>(cx: &Cx<'a,'tcx>, arm: &'tcx hir::Arm) -> Arm<Cx<'a,'tcx>> {
+fn convert_arm<'a, 'tcx: 'a>(cx: &Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
     let map = if arm.pats.len() == 1 {
         None
     } else {
         let mut map = FnvHashMap();
-        pat_util::pat_bindings(&cx.tcx.def_map, &arm.pats[0], |_, p_id, _, path| {
-            map.insert(path.node, p_id);
+        pat_util::pat_bindings_hygienic(&cx.tcx.def_map, &arm.pats[0], |_, p_id, _, path| {
+            map.insert(mtwt::resolve(path.node), p_id);
         });
         Some(Rc::new(map))
     };
 
-    Arm { patterns: arm.pats.iter().map(|p| PatNode::new(p, map.clone()).to_ref()).collect(),
-          guard: arm.guard.to_ref(),
-          body: arm.body.to_ref() }
+    Arm {
+        patterns: arm.pats.iter().map(|p| PatNode::new(p, map.clone()).to_ref()).collect(),
+        guard: arm.guard.to_ref(),
+        body: arm.body.to_ref(),
+    }
 }
 
-fn convert_path_expr<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
-                                 expr: &'tcx hir::Expr)
-                                 -> ExprKind<Cx<'a,'tcx>>
-{
+fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) -> ExprKind<'tcx> {
     let substs = cx.tcx.mk_substs(cx.tcx.node_id_item_substs(expr.id).substs);
     match cx.tcx.def_map.borrow()[&expr.id].full_def() {
         def::DefVariant(_, def_id, false) |
@@ -568,21 +520,20 @@ fn convert_path_expr<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
     }
 }
 
-fn convert_var<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
-                           expr: &'tcx hir::Expr,
-                           def: def::Def)
-                           -> ExprKind<Cx<'a,'tcx>>
-{
+fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
+                             expr: &'tcx hir::Expr,
+                             def: def::Def)
+                             -> ExprKind<'tcx> {
     let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
 
     match def {
-        def::DefLocal(node_id) => {
+        def::DefLocal(_, node_id) => {
             ExprKind::VarRef {
                 id: node_id,
             }
         }
 
-        def::DefUpvar(id_var, index, closure_expr_id) => {
+        def::DefUpvar(_, id_var, index, closure_expr_id) => {
             debug!("convert_var(upvar({:?}, {:?}, {:?}))", id_var, index, closure_expr_id);
             let var_ty = cx.tcx.node_id_to_type(id_var);
 
@@ -603,22 +554,18 @@ fn convert_var<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
             };
 
             // FIXME free regions in closures are not right
-            let closure_ty =
-                cx.tcx.node_id_to_type(closure_expr_id);
+            let closure_ty = cx.tcx.node_id_to_type(closure_expr_id);
 
             // FIXME we're just hard-coding the idea that the
             // signature will be &self or &mut self and hence will
             // have a bound region with number 0
-            let region =
-                ty::Region::ReFree(
-                    ty::FreeRegion {
-                        scope: cx.tcx.region_maps.node_extent(body_id),
-                        bound_region: ty::BoundRegion::BrAnon(0)
-                    });
-            let region =
-                cx.tcx.mk_region(region);
-
-            let self_expr = match cx.tcx.closure_kind(DefId::local(closure_expr_id)) {
+            let region = ty::Region::ReFree(ty::FreeRegion {
+                scope: cx.tcx.region_maps.node_extent(body_id),
+                bound_region: ty::BoundRegion::BrAnon(0),
+            });
+            let region = cx.tcx.mk_region(region);
+
+            let self_expr = match cx.tcx.closure_kind(cx.tcx.map.local_def_id(closure_expr_id)) {
                 ty::ClosureKind::FnClosureKind => {
                     let ref_closure_ty =
                         cx.tcx.mk_ref(region,
@@ -662,19 +609,23 @@ fn convert_var<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
                         ty: closure_ty,
                         temp_lifetime: temp_lifetime,
                         span: expr.span,
-                        kind: ExprKind::SelfRef
+                        kind: ExprKind::SelfRef,
                     }
                 }
             };
 
             // at this point we have `self.n`, which loads up the upvar
-            let field_kind =
-                ExprKind::Field { lhs: self_expr.to_ref(),
-                                  name: Field::Indexed(index) };
+            let field_kind = ExprKind::Field {
+                lhs: self_expr.to_ref(),
+                name: Field::Indexed(index),
+            };
 
             // ...but the upvar might be an `&T` or `&mut T` capture, at which
             // point we need an implicit deref
-            let upvar_id = ty::UpvarId { var_id: id_var, closure_expr_id: closure_expr_id };
+            let upvar_id = ty::UpvarId {
+                var_id: id_var,
+                closure_expr_id: closure_expr_id,
+            };
             let upvar_capture = match cx.tcx.upvar_capture(upvar_id) {
                 Some(c) => c,
                 None => {
@@ -698,7 +649,7 @@ fn convert_var<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
             }
         }
 
-        _ => cx.tcx.sess.span_bug(expr.span, "type of & not region")
+        _ => cx.tcx.sess.span_bug(expr.span, "type of & not region"),
     }
 }
 
@@ -721,23 +672,22 @@ fn bin_op(op: hir::BinOp_) -> BinOp {
         hir::BinOp_::BiNe => BinOp::Ne,
         hir::BinOp_::BiGe => BinOp::Ge,
         hir::BinOp_::BiGt => BinOp::Gt,
-        _ => panic!("no equivalent for ast binop {:?}", op)
+        _ => panic!("no equivalent for ast binop {:?}", op),
     }
 }
 
 enum PassArgs {
     ByValue,
-    ByRef
+    ByRef,
 }
 
-fn overloaded_operator<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
-                                   expr: &'tcx hir::Expr,
-                                   method_call: ty::MethodCall,
-                                   pass_args: PassArgs,
-                                   receiver: ExprRef<Cx<'a,'tcx>>,
-                                   args: Vec<&'tcx P<hir::Expr>>)
-                                   -> ExprKind<Cx<'a,'tcx>>
-{
+fn overloaded_operator<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
+                                     expr: &'tcx hir::Expr,
+                                     method_call: ty::MethodCall,
+                                     pass_args: PassArgs,
+                                     receiver: ExprRef<'tcx>,
+                                     args: Vec<&'tcx P<hir::Expr>>)
+                                     -> ExprKind<'tcx> {
     // the receiver has all the adjustments that are needed, so we can
     // just push a reference to it
     let mut argrefs = vec![receiver];
@@ -746,9 +696,7 @@ fn overloaded_operator<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
     // operator, we have to gin up the autorefs (but by value is easy)
     match pass_args {
         PassArgs::ByValue => {
-            argrefs.extend(
-                args.iter()
-                    .map(|arg| arg.to_ref()))
+            argrefs.extend(args.iter().map(|arg| arg.to_ref()))
         }
 
         PassArgs::ByRef => {
@@ -783,14 +731,13 @@ fn overloaded_operator<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
     }
 }
 
-fn overloaded_lvalue<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
-                                 expr: &'tcx hir::Expr,
-                                 method_call: ty::MethodCall,
-                                 pass_args: PassArgs,
-                                 receiver: ExprRef<Cx<'a,'tcx>>,
-                                 args: Vec<&'tcx P<hir::Expr>>)
-                                 -> ExprKind<Cx<'a,'tcx>>
-{
+fn overloaded_lvalue<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
+                                   expr: &'tcx hir::Expr,
+                                   method_call: ty::MethodCall,
+                                   pass_args: PassArgs,
+                                   receiver: ExprRef<'tcx>,
+                                   args: Vec<&'tcx P<hir::Expr>>)
+                                   -> ExprKind<'tcx> {
     // For an overloaded *x or x[y] expression of type T, the method
     // call returns an &T and we must add the deref so that the types
     // line up (this is because `*x` and `x[y]` represent lvalues):
@@ -819,20 +766,25 @@ fn overloaded_lvalue<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
     ExprKind::Deref { arg: ref_expr.to_ref() }
 }
 
-fn capture_freevar<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
-                               closure_expr: &'tcx hir::Expr,
-                               freevar: &ty::Freevar,
-                               freevar_ty: Ty<'tcx>)
-                               -> ExprRef<Cx<'a,'tcx>> {
-    let id_var = freevar.def.def_id().node;
-    let upvar_id = ty::UpvarId { var_id: id_var, closure_expr_id: closure_expr.id };
+fn capture_freevar<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
+                                 closure_expr: &'tcx hir::Expr,
+                                 freevar: &ty::Freevar,
+                                 freevar_ty: Ty<'tcx>)
+                                 -> ExprRef<'tcx> {
+    let id_var = freevar.def.var_id();
+    let upvar_id = ty::UpvarId {
+        var_id: id_var,
+        closure_expr_id: closure_expr.id,
+    };
     let upvar_capture = cx.tcx.upvar_capture(upvar_id).unwrap();
     let temp_lifetime = cx.tcx.region_maps.temporary_scope(closure_expr.id);
     let var_ty = cx.tcx.node_id_to_type(id_var);
-    let captured_var = Expr { temp_lifetime: temp_lifetime,
-                              ty: var_ty,
-                              span: closure_expr.span,
-                              kind: convert_var(cx, closure_expr, freevar.def) };
+    let captured_var = Expr {
+        temp_lifetime: temp_lifetime,
+        ty: var_ty,
+        span: closure_expr.span,
+        kind: convert_var(cx, closure_expr, freevar.def),
+    };
     match upvar_capture {
         ty::UpvarCapture::ByValue => {
             captured_var.to_ref()
@@ -855,16 +807,11 @@ fn capture_freevar<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
     }
 }
 
-fn loop_label<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
-                          expr: &'tcx hir::Expr)
-                          -> CodeExtent
-{
+fn loop_label<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) -> CodeExtent {
     match cx.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
         Some(def::DefLabel(loop_id)) => cx.tcx.region_maps.node_extent(loop_id),
         d => {
-            cx.tcx.sess.span_bug(
-                expr.span,
-                &format!("loop scope resolved to {:?}", d));
+            cx.tcx.sess.span_bug(expr.span, &format!("loop scope resolved to {:?}", d));
         }
     }
 }
index 2e9eae0956d9693700a6245cb5913aff269dbb51..92b026e5035b43f9d10c8e5686786437cac02294 100644 (file)
@@ -8,88 +8,86 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+/*!
+ * This module contains the code to convert from the wacky tcx data
+ * structures into the hair. The `builder` is generally ignorant of
+ * the tcx etc, and instead goes through the `Cx` for most of its
+ * work.
+ */
+
 use hair::*;
 use repr::*;
-use std::fmt::{Debug, Formatter, Error};
-use std::hash::{Hash, Hasher};
-use std::rc::Rc;
-
-use self::rustc::middle::def_id::DefId;
-use self::rustc::middle::infer::InferCtxt;
-use self::rustc::middle::region::CodeExtent;
-use self::rustc::middle::subst::{self, Subst, Substs};
-use self::rustc::middle::ty::{self, Ty};
-use self::rustc_front::hir;
-use self::syntax::ast;
-use self::syntax::codemap::Span;
-use self::syntax::parse::token::{self, special_idents, InternedString};
-
-extern crate rustc;
-extern crate rustc_front;
-extern crate syntax;
+
+use rustc::middle::const_eval::ConstVal;
+use rustc::middle::def_id::DefId;
+use rustc::middle::infer::InferCtxt;
+use rustc::middle::subst::{Subst, Substs};
+use rustc::middle::ty::{self, Ty};
+use syntax::codemap::Span;
+use syntax::parse::token::{self, special_idents};
 
 #[derive(Copy, Clone)]
-pub struct Cx<'a,'tcx:'a> {
-    pub tcx: &'a ty::ctxt<'tcx>,
-    pub infcx: &'a InferCtxt<'a,'tcx>,
+pub struct Cx<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>,
+    infcx: &'a InferCtxt<'a, 'tcx>,
 }
 
 impl<'a,'tcx> Cx<'a,'tcx> {
-    pub fn new(infcx: &'a InferCtxt<'a,'tcx>) -> Cx<'a,'tcx> {
-        Cx { tcx: infcx.tcx, infcx: infcx }
+    pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Cx<'a, 'tcx> {
+        Cx {
+            tcx: infcx.tcx,
+            infcx: infcx,
+        }
     }
 }
 
 pub use self::pattern::PatNode;
 
-impl<'a,'tcx:'a> Hair for Cx<'a, 'tcx> {
-    type VarId = ast::NodeId;
-    type DefId = DefId;
-    type AdtDef = ty::AdtDef<'tcx>;
-    type Name = ast::Name;
-    type Ident = ast::Ident;
-    type InternedString = InternedString;
-    type Bytes = Rc<Vec<u8>>;
-    type Span = Span;
-    type Projection = ty::ProjectionTy<'tcx>;
-    type Substs = &'tcx subst::Substs<'tcx>;
-    type ClosureSubsts = &'tcx ty::ClosureSubsts<'tcx>;
-    type Ty = Ty<'tcx>;
-    type Region = ty::Region;
-    type CodeExtent = CodeExtent;
-    type Pattern = PatNode<'tcx>;
-    type Expr = &'tcx hir::Expr;
-    type Stmt = &'tcx hir::Stmt;
-    type Block = &'tcx hir::Block;
-    type InlineAsm = &'tcx hir::InlineAsm;
-
-    fn unit_ty(&mut self) -> Ty<'tcx> {
+impl<'a,'tcx:'a> Cx<'a, 'tcx> {
+    /// Normalizes `ast` into the appropriate `mirror` type.
+    pub fn mirror<M: Mirror<'tcx>>(&mut self, ast: M) -> M::Output {
+        ast.make_mirror(self)
+    }
+
+    pub fn unit_ty(&mut self) -> Ty<'tcx> {
         self.tcx.mk_nil()
     }
 
-    fn usize_ty(&mut self) -> Ty<'tcx> {
+    pub fn usize_ty(&mut self) -> Ty<'tcx> {
         self.tcx.types.usize
     }
 
-    fn bool_ty(&mut self) -> Ty<'tcx> {
+    pub fn usize_literal(&mut self, value: usize) -> Literal<'tcx> {
+        Literal::Value { value: ConstVal::Uint(value as u64) }
+    }
+
+    pub fn bool_ty(&mut self) -> Ty<'tcx> {
         self.tcx.types.bool
     }
 
-    fn partial_eq(&mut self, ty: Ty<'tcx>) -> ItemRef<Self> {
+    pub fn true_literal(&mut self) -> Literal<'tcx> {
+        Literal::Value { value: ConstVal::Bool(true) }
+    }
+
+    pub fn false_literal(&mut self) -> Literal<'tcx> {
+        Literal::Value { value: ConstVal::Bool(false) }
+    }
+
+    pub fn partial_eq(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> {
         let eq_def_id = self.tcx.lang_items.eq_trait().unwrap();
         self.cmp_method_ref(eq_def_id, "eq", ty)
     }
 
-    fn partial_le(&mut self, ty: Ty<'tcx>) -> ItemRef<Self> {
+    pub fn partial_le(&mut self, ty: Ty<'tcx>) -> ItemRef<'tcx> {
         let ord_def_id = self.tcx.lang_items.ord_trait().unwrap();
         self.cmp_method_ref(ord_def_id, "le", ty)
     }
 
-    fn num_variants(&mut self, adt_def: ty::AdtDef<'tcx>) -> usize {
+    pub fn num_variants(&mut self, adt_def: ty::AdtDef<'tcx>) -> usize {
         adt_def.variants.len()
     }
 
-    fn fields(&mut self, adt_def: ty::AdtDef<'tcx>, variant_index: usize) -> Vec<Field<Self>> {
+    pub fn fields(&mut self, adt_def: ty::AdtDef<'tcx>, variant_index: usize) -> Vec<Field> {
         adt_def.variants[variant_index]
             .fields
             .iter()
@@ -104,7 +102,7 @@ impl<'a,'tcx:'a> Hair for Cx<'a, 'tcx> {
             .collect()
     }
 
-    fn needs_drop(&mut self, ty: Ty<'tcx>, span: Self::Span) -> bool {
+    pub fn needs_drop(&mut self, ty: Ty<'tcx>, span: Span) -> bool {
         if self.infcx.type_moves_by_default(ty, span) {
             // FIXME(#21859) we should do an add'l check here to determine if
             // any dtor will execute, but the relevant fn
@@ -117,17 +115,19 @@ impl<'a,'tcx:'a> Hair for Cx<'a, 'tcx> {
         }
     }
 
-    fn span_bug(&mut self, span: Self::Span, message: &str) -> ! {
+    pub fn span_bug(&mut self, span: Span, message: &str) -> ! {
         self.tcx.sess.span_bug(span, message)
     }
-}
 
-impl<'a,'tcx:'a> Cx<'a,'tcx> {
+    pub fn tcx(&self) -> &'a ty::ctxt<'tcx> {
+        self.tcx
+    }
+
     fn cmp_method_ref(&mut self,
                       trait_def_id: DefId,
                       method_name: &str,
                       arg_ty: Ty<'tcx>)
-                      -> ItemRef<Cx<'a,'tcx>> {
+                      -> ItemRef<'tcx> {
         let method_name = token::intern(method_name);
         let substs = Substs::new_trait(vec![arg_ty], vec![], arg_ty);
         for trait_item in self.tcx.trait_items(trait_def_id).iter() {
@@ -144,36 +144,11 @@ impl<'a,'tcx:'a> Cx<'a,'tcx> {
                     }
                 }
                 ty::ImplOrTraitItem::ConstTraitItem(..) |
-                ty::ImplOrTraitItem::TypeTraitItem(..) => {
-                }
+                ty::ImplOrTraitItem::TypeTraitItem(..) => {}
             }
         }
 
-        self.tcx.sess.bug(
-            &format!("found no method `{}` in `{:?}`", method_name, trait_def_id));
-    }
-}
-
-// We only need this impl so that we do deriving for things that are
-// defined relative to the `Hair` trait. See `Hair` trait for more
-// details.
-impl<'a,'tcx> PartialEq for Cx<'a,'tcx> {
-    fn eq(&self, _: &Cx<'a,'tcx>) -> bool {
-        panic!("Cx should never ACTUALLY be compared for equality")
-    }
-}
-
-impl<'a,'tcx> Eq for Cx<'a,'tcx> { }
-
-impl<'a,'tcx> Hash for Cx<'a,'tcx> {
-    fn hash<H: Hasher>(&self, _: &mut H) {
-        panic!("Cx should never ACTUALLY be hashed")
-    }
-}
-
-impl<'a,'tcx> Debug for Cx<'a,'tcx> {
-    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
-        write!(fmt, "Tcx")
+        self.tcx.sess.bug(&format!("found no method `{}` in `{:?}`", method_name, trait_def_id));
     }
 }
 
@@ -181,4 +156,3 @@ mod block;
 mod expr;
 mod pattern;
 mod to_ref;
-
index eee0911f1cd9ef51708d89ba9b85b7cd1bb432c5..bb68ae825f2f7b92ccd234abf346b2d2b9d5c743 100644 (file)
@@ -14,14 +14,16 @@ use repr::*;
 use rustc_data_structures::fnv::FnvHashMap;
 use std::rc::Rc;
 use tcx::Cx;
-use tcx::rustc::middle::const_eval::lookup_const_by_id;
-use tcx::rustc::middle::def;
-use tcx::rustc::middle::pat_util::{pat_is_resolved_const, pat_is_binding};
-use tcx::rustc::middle::ty::{self, Ty};
-use tcx::rustc_front::hir;
-use tcx::syntax::ast;
-use tcx::syntax::ptr::P;
 use tcx::to_ref::ToRef;
+use rustc::middle::const_eval;
+use rustc::middle::def;
+use rustc::middle::pat_util::{pat_is_resolved_const, pat_is_binding};
+use rustc::middle::subst::Substs;
+use rustc::middle::ty::{self, Ty};
+use rustc_front::hir;
+use syntax::ast;
+use syntax::ext::mtwt;
+use syntax::ptr::P;
 
 /// When there are multiple patterns in a single arm, each one has its
 /// own node-ids for the bindings.  References to the variables always
@@ -39,12 +41,12 @@ use tcx::to_ref::ToRef;
 #[derive(Clone, Debug)]
 pub struct PatNode<'tcx> {
     pat: &'tcx hir::Pat,
-    binding_map: Option<Rc<FnvHashMap<ast::Ident, ast::NodeId>>>
+    binding_map: Option<Rc<FnvHashMap<ast::Name, ast::NodeId>>>,
 }
 
 impl<'tcx> PatNode<'tcx> {
     pub fn new(pat: &'tcx hir::Pat,
-               binding_map: Option<Rc<FnvHashMap<ast::Ident, ast::NodeId>>>)
+               binding_map: Option<Rc<FnvHashMap<ast::Name, ast::NodeId>>>)
                -> PatNode<'tcx> {
         PatNode {
             pat: pat,
@@ -52,20 +54,19 @@ impl<'tcx> PatNode<'tcx> {
         }
     }
 
-    pub fn irrefutable(pat: &'tcx hir::Pat)
-                       -> PatNode<'tcx> {
+    pub fn irrefutable(pat: &'tcx hir::Pat) -> PatNode<'tcx> {
         PatNode::new(pat, None)
     }
 
-    fn pat_ref<'a>(&self, pat: &'tcx hir::Pat) -> PatternRef<Cx<'a,'tcx>> {
+    fn pat_ref<'a>(&self, pat: &'tcx hir::Pat) -> PatternRef<'tcx> {
         PatNode::new(pat, self.binding_map.clone()).to_ref()
     }
 
-    fn pat_refs<'a>(&self, pats: &'tcx Vec<P<hir::Pat>>) -> Vec<PatternRef<Cx<'a,'tcx>>> {
+    fn pat_refs<'a>(&self, pats: &'tcx Vec<P<hir::Pat>>) -> Vec<PatternRef<'tcx>> {
         pats.iter().map(|p| self.pat_ref(p)).collect()
     }
 
-    fn opt_pat_ref<'a>(&self, pat: &'tcx Option<P<hir::Pat>>) -> Option<PatternRef<Cx<'a,'tcx>>> {
+    fn opt_pat_ref<'a>(&self, pat: &'tcx Option<P<hir::Pat>>) -> Option<PatternRef<'tcx>> {
         pat.as_ref().map(|p| self.pat_ref(p))
     }
 
@@ -75,8 +76,7 @@ impl<'tcx> PatNode<'tcx> {
                                   prefix: &'tcx Vec<P<hir::Pat>>,
                                   slice: &'tcx Option<P<hir::Pat>>,
                                   suffix: &'tcx Vec<P<hir::Pat>>)
-                                  -> PatternKind<Cx<'a,'tcx>>
-    {
+                                  -> PatternKind<'tcx> {
         match ty.sty {
             ty::TySlice(..) =>
                 // matching a slice or fixed-length array
@@ -97,26 +97,25 @@ impl<'tcx> PatNode<'tcx> {
             }
 
             _ => {
-                cx.tcx.sess.span_bug(
-                    self.pat.span,
-                    "unexpanded macro or bad constant etc");
+                cx.tcx.sess.span_bug(self.pat.span, "unexpanded macro or bad constant etc");
             }
         }
     }
 
     fn variant_or_leaf<'a>(&self,
                            cx: &mut Cx<'a, 'tcx>,
-                           subpatterns: Vec<FieldPatternRef<Cx<'a,'tcx>>>)
-                           -> PatternKind<Cx<'a,'tcx>>
-    {
+                           subpatterns: Vec<FieldPatternRef<'tcx>>)
+                           -> PatternKind<'tcx> {
         let def = cx.tcx.def_map.borrow().get(&self.pat.id).unwrap().full_def();
         match def {
             def::DefVariant(enum_id, variant_id, _) => {
                 let adt_def = cx.tcx.lookup_adt_def(enum_id);
                 if adt_def.variants.len() > 1 {
-                    PatternKind::Variant { adt_def: adt_def,
-                                           variant_index: adt_def.variant_index_with_id(variant_id),
-                                           subpatterns: subpatterns }
+                    PatternKind::Variant {
+                        adt_def: adt_def,
+                        variant_index: adt_def.variant_index_with_id(variant_id),
+                        subpatterns: subpatterns,
+                    }
                 } else {
                     PatternKind::Leaf { subpatterns: subpatterns }
                 }
@@ -129,28 +128,33 @@ impl<'tcx> PatNode<'tcx> {
             }
 
             _ => {
-                cx.tcx.sess.span_bug(
-                    self.pat.span,
-                    &format!("inappropriate def for pattern: {:?}", def));
+                cx.tcx.sess.span_bug(self.pat.span,
+                                     &format!("inappropriate def for pattern: {:?}", def));
             }
         }
     }
 }
 
-impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for PatNode<'tcx> {
-    type Output = Pattern<Cx<'a,'tcx>>;
+impl<'tcx> Mirror<'tcx> for PatNode<'tcx> {
+    type Output = Pattern<'tcx>;
 
-    fn make_mirror(self, cx: &mut Cx<'a,'tcx>) -> Pattern<Cx<'a,'tcx>> {
+    fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Pattern<'tcx> {
         let kind = match self.pat.node {
-            hir::PatWild(..) =>
-                PatternKind::Wild,
+            hir::PatWild(..) => PatternKind::Wild,
 
-            hir::PatLit(ref lt) =>
-                PatternKind::Constant { expr: lt.to_ref() },
+            hir::PatLit(ref value) => {
+                let value = const_eval::eval_const_expr(cx.tcx, value);
+                let value = Literal::Value { value: value };
+                PatternKind::Constant { value: value }
+            }
 
-            hir::PatRange(ref begin, ref end) =>
-                PatternKind::Range { lo: begin.to_ref(),
-                                     hi: end.to_ref() },
+            hir::PatRange(ref lo, ref hi) => {
+                let lo = const_eval::eval_const_expr(cx.tcx, lo);
+                let lo = Literal::Value { value: lo };
+                let hi = const_eval::eval_const_expr(cx.tcx, hi);
+                let hi = Literal::Value { value: hi };
+                PatternKind::Range { lo: lo, hi: hi }
+            },
 
             hir::PatEnum(..) | hir::PatIdent(..) | hir::PatQPath(..)
                 if pat_is_resolved_const(&cx.tcx.def_map, self.pat) =>
@@ -158,13 +162,26 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for PatNode<'tcx> {
                 let def = cx.tcx.def_map.borrow().get(&self.pat.id).unwrap().full_def();
                 match def {
                     def::DefConst(def_id) | def::DefAssociatedConst(def_id) =>
-                        match lookup_const_by_id(cx.tcx, def_id, Some(self.pat.id)) {
-                            Some(const_expr) =>
-                                PatternKind::Constant { expr: const_expr.to_ref() },
-                            None =>
+                        match const_eval::lookup_const_by_id(cx.tcx, def_id, Some(self.pat.id)) {
+                            Some(const_expr) => {
+                                let opt_value =
+                                    const_eval::eval_const_expr_partial(
+                                        cx.tcx, const_expr,
+                                        const_eval::EvalHint::ExprTypeChecked,
+                                        None);
+                                let literal = if let Ok(value) = opt_value {
+                                    Literal::Value { value: value }
+                                } else {
+                                    let substs = cx.tcx.mk_substs(Substs::empty());
+                                    Literal::Item { def_id: def_id, substs: substs }
+                                };
+                                PatternKind::Constant { value: literal }
+                            }
+                            None => {
                                 cx.tcx.sess.span_bug(
                                     self.pat.span,
-                                    &format!("cannot eval constant: {:?}", def_id)),
+                                    &format!("cannot eval constant: {:?}", def_id))
+                            }
                         },
                     _ =>
                         cx.tcx.sess.span_bug(
@@ -220,7 +237,7 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for PatNode<'tcx> {
             {
                 let id = match self.binding_map {
                     None => self.pat.id,
-                    Some(ref map) => map[&ident.node],
+                    Some(ref map) => map[&mtwt::resolve(ident.node)],
                 };
                 let var_ty = cx.tcx.node_id_to_type(self.pat.id);
                 let region = match var_ty.sty {
@@ -240,7 +257,7 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for PatNode<'tcx> {
                 PatternKind::Binding {
                     mutability: mutability,
                     mode: mode,
-                    name: ident.node,
+                    name: ident.node.name,
                     var: id,
                     ty: var_ty,
                     subpattern: self.opt_pat_ref(sub),
@@ -268,7 +285,7 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for PatNode<'tcx> {
                 let subpatterns =
                     fields.iter()
                           .map(|field| FieldPatternRef {
-                              field: Field::Named(field.node.ident.name),
+                              field: Field::Named(field.node.name),
                               pattern: self.pat_ref(&field.node.pat),
                           })
                           .collect();
@@ -276,16 +293,16 @@ impl<'a,'tcx:'a> Mirror<Cx<'a,'tcx>> for PatNode<'tcx> {
             }
 
             hir::PatQPath(..) => {
-                cx.tcx.sess.span_bug(
-                    self.pat.span,
-                    "unexpanded macro or bad constant etc");
+                cx.tcx.sess.span_bug(self.pat.span, "unexpanded macro or bad constant etc");
             }
         };
 
         let ty = cx.tcx.node_id_to_type(self.pat.id);
 
-        Pattern { span: self.pat.span,
-                  ty: ty,
-                  kind: kind }
+        Pattern {
+            span: self.pat.span,
+            ty: ty,
+            kind: kind,
+        }
     }
 }
index 6d5e4c2e3fd7a3e13682266d1b4c1cd70c727da3..13ca82e3e4c7188e3be1ae996911e9a9151d5b36 100644 (file)
 use hair::*;
 use repr::*;
 
-use tcx::Cx;
 use tcx::pattern::PatNode;
-use tcx::rustc_front::hir;
-use tcx::syntax::ptr::P;
+use rustc_front::hir;
+use syntax::ptr::P;
 
-pub trait ToRef<H> {
+pub trait ToRef {
     type Output;
     fn to_ref(self) -> Self::Output;
 }
 
-impl<'a,'tcx:'a> ToRef<Cx<'a,'tcx>> for &'tcx hir::Expr {
-    type Output = ExprRef<Cx<'a,'tcx>>;
+impl<'a,'tcx:'a> ToRef for &'tcx hir::Expr {
+    type Output = ExprRef<'tcx>;
 
-    fn to_ref(self) -> ExprRef<Cx<'a,'tcx>> {
+    fn to_ref(self) -> ExprRef<'tcx> {
         ExprRef::Hair(self)
     }
 }
 
-impl<'a,'tcx:'a> ToRef<Cx<'a,'tcx>> for &'tcx P<hir::Expr> {
-    type Output = ExprRef<Cx<'a,'tcx>>;
+impl<'a,'tcx:'a> ToRef for &'tcx P<hir::Expr> {
+    type Output = ExprRef<'tcx>;
 
-    fn to_ref(self) -> ExprRef<Cx<'a,'tcx>> {
+    fn to_ref(self) -> ExprRef<'tcx> {
         ExprRef::Hair(&**self)
     }
 }
 
-impl<'a,'tcx:'a> ToRef<Cx<'a,'tcx>> for Expr<Cx<'a,'tcx>> {
-    type Output = ExprRef<Cx<'a,'tcx>>;
+impl<'a,'tcx:'a> ToRef for Expr<'tcx> {
+    type Output = ExprRef<'tcx>;
 
-    fn to_ref(self) -> ExprRef<Cx<'a,'tcx>> {
+    fn to_ref(self) -> ExprRef<'tcx> {
         ExprRef::Mirror(Box::new(self))
     }
 }
 
-impl<'a,'tcx:'a> ToRef<Cx<'a,'tcx>> for PatNode<'tcx> {
-    type Output = PatternRef<Cx<'a,'tcx>>;
+impl<'a,'tcx:'a> ToRef for PatNode<'tcx> {
+    type Output = PatternRef<'tcx>;
 
-    fn to_ref(self) -> PatternRef<Cx<'a,'tcx>> {
+    fn to_ref(self) -> PatternRef<'tcx> {
         PatternRef::Hair(self)
     }
 }
 
-impl<'a,'tcx:'a> ToRef<Cx<'a,'tcx>> for Pattern<Cx<'a,'tcx>> {
-    type Output = PatternRef<Cx<'a,'tcx>>;
+impl<'a,'tcx:'a> ToRef for Pattern<'tcx> {
+    type Output = PatternRef<'tcx>;
 
-    fn to_ref(self) -> PatternRef<Cx<'a,'tcx>> {
+    fn to_ref(self) -> PatternRef<'tcx> {
         PatternRef::Mirror(Box::new(self))
     }
 }
 
-impl<'a,'tcx:'a,T,U> ToRef<Cx<'a,'tcx>> for &'tcx Option<T>
-    where &'tcx T: ToRef<Cx<'a,'tcx>, Output=U>
+impl<'a,'tcx:'a,T,U> ToRef for &'tcx Option<T>
+    where &'tcx T: ToRef<Output=U>
 {
     type Output = Option<U>;
 
@@ -71,8 +70,8 @@ impl<'a,'tcx:'a,T,U> ToRef<Cx<'a,'tcx>> for &'tcx Option<T>
     }
 }
 
-impl<'a,'tcx:'a,T,U> ToRef<Cx<'a,'tcx>> for &'tcx Vec<T>
-    where &'tcx T: ToRef<Cx<'a,'tcx>, Output=U>
+impl<'a,'tcx:'a,T,U> ToRef for &'tcx Vec<T>
+    where &'tcx T: ToRef<Output=U>
 {
     type Output = Vec<U>;
 
@@ -81,14 +80,13 @@ impl<'a,'tcx:'a,T,U> ToRef<Cx<'a,'tcx>> for &'tcx Vec<T>
     }
 }
 
-impl<'a,'tcx:'a> ToRef<Cx<'a,'tcx>> for &'tcx hir::Field {
-    type Output = FieldExprRef<Cx<'a,'tcx>>;
+impl<'a,'tcx:'a> ToRef for &'tcx hir::Field {
+    type Output = FieldExprRef<'tcx>;
 
-    fn to_ref(self) -> FieldExprRef<Cx<'a,'tcx>> {
+    fn to_ref(self) -> FieldExprRef<'tcx> {
         FieldExprRef {
-            name: Field::Named(self.ident.node.name),
-            expr: self.expr.to_ref()
+            name: Field::Named(self.name.node),
+            expr: self.expr.to_ref(),
         }
     }
 }
-
index 48efd34e2122036abe992980b0489944cfd4a985..dd990abaa9aa3241d1c492db683db8fd4e3e2eda 100644 (file)
@@ -82,7 +82,7 @@ impl<'v> Visitor<'v> for ParentVisitor {
                     // The parent is considered the enclosing enum because the
                     // enum will dictate the privacy visibility of this variant
                     // instead.
-                    self.parents.insert(variant.node.id, item.id);
+                    self.parents.insert(variant.node.data.id(), item.id);
                 }
             }
 
@@ -128,18 +128,17 @@ impl<'v> Visitor<'v> for ParentVisitor {
         visit::walk_impl_item(self, ii);
     }
 
-    fn visit_struct_def(&mut self, s: &hir::StructDef, _: ast::Ident,
-                        _: &'v hir::Generics, n: ast::NodeId) {
+    fn visit_variant_data(&mut self, s: &hir::VariantData, _: ast::Name,
+                        _: &'v hir::Generics, item_id: ast::NodeId, _: Span) {
         // Struct constructors are parented to their struct definitions because
         // they essentially are the struct definitions.
-        match s.ctor_id {
-            Some(id) => { self.parents.insert(id, n); }
-            None => {}
+        if !s.is_struct() {
+            self.parents.insert(s.id(), item_id);
         }
 
         // While we have the id of the struct definition, go ahead and parent
         // all the fields.
-        for field in &s.fields {
+        for field in s.fields() {
             self.parents.insert(field.node.id, self.curparent);
         }
         visit::walk_struct_def(self, s)
@@ -234,8 +233,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
             // public all variants are public unless they're explicitly priv
             hir::ItemEnum(ref def, _) if public_first => {
                 for variant in &def.variants {
-                    self.exported_items.insert(variant.node.id);
-                    self.public_items.insert(variant.node.id);
+                    self.exported_items.insert(variant.node.data.id());
+                    self.public_items.insert(variant.node.data.id());
                 }
             }
 
@@ -263,19 +262,26 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
                     hir::TyPath(..) => {
                         match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() {
                             def::DefPrimTy(..) => true,
+                            def::DefSelfTy(..) => true,
                             def => {
                                 let did = def.def_id();
-                                !did.is_local() ||
-                                 self.exported_items.contains(&did.node)
+                                if let Some(node_id) = self.tcx.map.as_local_node_id(did) {
+                                    self.exported_items.contains(&node_id)
+                                } else {
+                                    true
+                                }
                             }
                         }
                     }
                     _ => true,
                 };
-                let tr = self.tcx.impl_trait_ref(DefId::local(item.id));
+                let tr = self.tcx.impl_trait_ref(self.tcx.map.local_def_id(item.id));
                 let public_trait = tr.clone().map_or(false, |tr| {
-                    !tr.def_id.is_local() ||
-                     self.exported_items.contains(&tr.def_id.node)
+                    if let Some(node_id) = self.tcx.map.as_local_node_id(tr.def_id) {
+                        self.exported_items.contains(&node_id)
+                    } else {
+                        true
+                    }
                 });
 
                 if public_ty || public_trait {
@@ -313,12 +319,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
 
             // Struct constructors are public if the struct is all public.
             hir::ItemStruct(ref def, _) if public_first => {
-                match def.ctor_id {
-                    Some(id) => { self.exported_items.insert(id); }
-                    None => {}
+                if !def.is_struct() {
+                    self.exported_items.insert(def.id());
                 }
                 // fields can be public or private, so lets check
-                for field in &def.fields {
+                for field in def.fields() {
                     let vis = match field.node.kind {
                         hir::NamedField(_, vis) | hir::UnnamedField(vis) => vis
                     };
@@ -331,11 +336,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
             hir::ItemTy(ref ty, _) if public_first => {
                 if let hir::TyPath(..) = ty.node {
                     match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() {
-                        def::DefPrimTy(..) | def::DefTyParam(..) => {},
+                        def::DefPrimTy(..) | def::DefSelfTy(..) | def::DefTyParam(..) => {},
                         def => {
                             let did = def.def_id();
-                            if did.is_local() {
-                                self.exported_items.insert(did.node);
+                            if let Some(node_id) = self.tcx.map.as_local_node_id(did) {
+                                self.exported_items.insert(node_id);
                             }
                         }
                     }
@@ -363,8 +368,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
         if self.prev_exported {
             assert!(self.export_map.contains_key(&id), "wut {}", id);
             for export in self.export_map.get(&id).unwrap() {
-                if export.def_id.is_local() {
-                    self.reexports.insert(export.def_id.node);
+                if let Some(node_id) = self.tcx.map.as_local_node_id(export.def_id) {
+                    self.reexports.insert(node_id);
                 }
             }
         }
@@ -384,6 +389,7 @@ struct PrivacyVisitor<'a, 'tcx: 'a> {
     external_exports: ExternalExports,
 }
 
+#[derive(Debug)]
 enum PrivacyResult {
     Allowable,
     ExternallyDenied,
@@ -392,7 +398,6 @@ enum PrivacyResult {
 
 enum FieldName {
     UnnamedField(usize), // index
-    // (Name, not Ident, because struct fields are not macro-hygienic)
     NamedField(ast::Name),
 }
 
@@ -405,7 +410,9 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
     // Determines whether the given definition is public from the point of view
     // of the current item.
     fn def_privacy(&self, did: DefId) -> PrivacyResult {
-        if !did.is_local() {
+        let node_id = if let Some(node_id) = self.tcx.map.as_local_node_id(did) {
+            node_id
+        } else {
             if self.external_exports.contains(&did) {
                 debug!("privacy - {:?} was externally exported", did);
                 return Allowable;
@@ -497,19 +504,19 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                     ExternallyDenied
                 }
             };
-        }
+        };
 
         debug!("privacy - local {} not public all the way down",
-               self.tcx.map.node_to_string(did.node));
+               self.tcx.map.node_to_string(node_id));
         // return quickly for things in the same module
-        if self.parents.get(&did.node) == self.parents.get(&self.curitem) {
+        if self.parents.get(&node_id) == self.parents.get(&self.curitem) {
             debug!("privacy - same parent, we're done here");
             return Allowable;
         }
 
         // We now know that there is at least one private member between the
         // destination and the root.
-        let mut closest_private_id = did.node;
+        let mut closest_private_id = node_id;
         loop {
             debug!("privacy - examining {}", self.nodestr(closest_private_id));
             let vis = match self.tcx.map.find(closest_private_id) {
@@ -579,6 +586,15 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
         }
     }
 
+    /// True if `id` is both local and private-accessible
+    fn local_private_accessible(&self, did: DefId) -> bool {
+        if let Some(node_id) = self.tcx.map.as_local_node_id(did) {
+            self.private_accessible(node_id)
+        } else {
+            false
+        }
+    }
+
     /// For a local private node in the AST, this function will determine
     /// whether the node is accessible by the current module that iteration is
     /// inside.
@@ -630,9 +646,17 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
     /// Guarantee that a particular definition is public. Returns a CheckResult
     /// which contains any errors found. These can be reported using `report_error`.
     /// If the result is `None`, no errors were found.
-    fn ensure_public(&self, span: Span, to_check: DefId,
-                     source_did: Option<DefId>, msg: &str) -> CheckResult {
-        let id = match self.def_privacy(to_check) {
+    fn ensure_public(&self,
+                     span: Span,
+                     to_check: DefId,
+                     source_did: Option<DefId>,
+                     msg: &str)
+                     -> CheckResult {
+        debug!("ensure_public(span={:?}, to_check={:?}, source_did={:?}, msg={:?})",
+               span, to_check, source_did, msg);
+        let def_privacy = self.def_privacy(to_check);
+        debug!("ensure_public: def_privacy={:?}", def_privacy);
+        let id = match def_privacy {
             ExternallyDenied => {
                 return Some((span, format!("{} is private", msg), None))
             }
@@ -640,11 +664,15 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
             DisallowedBy(id) => id,
         };
 
-        // If we're disallowed by a particular id, then we attempt to give a
-        // nice error message to say why it was disallowed. It was either
-        // because the item itself is private or because its parent is private
-        // and its parent isn't in our ancestry.
-        let (err_span, err_msg) = if id == source_did.unwrap_or(to_check).node {
+        // If we're disallowed by a particular id, then we attempt to
+        // give a nice error message to say why it was disallowed. It
+        // was either because the item itself is private or because
+        // its parent is private and its parent isn't in our
+        // ancestry. (Both the item being checked and its parent must
+        // be local.)
+        let def_id = source_did.unwrap_or(to_check);
+        let node_id = self.tcx.map.as_local_node_id(def_id);
+        let (err_span, err_msg) = if Some(id) == node_id {
             return Some((span, format!("{} is private", msg), None));
         } else {
             (span, format!("{} is inaccessible", msg))
@@ -664,8 +692,8 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                         };
                         let def = self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def();
                         let did = def.def_id();
-                        assert!(did.is_local());
-                        match self.tcx.map.get(did.node) {
+                        let node_id = self.tcx.map.as_local_node_id(did).unwrap();
+                        match self.tcx.map.get(node_id) {
                             ast_map::NodeItem(item) => item,
                             _ => self.tcx.sess.span_bug(item.span,
                                                         "path is not an item")
@@ -683,7 +711,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
             hir::ItemEnum(..) => "enum",
             _ => return Some((err_span, err_msg, None))
         };
-        let msg = format!("{} `{}` is private", desc, item.ident);
+        let msg = format!("{} `{}` is private", desc, item.name);
         Some((err_span, err_msg, Some((span, msg))))
     }
 
@@ -700,9 +728,8 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
             }
             UnnamedField(idx) => &v.fields[idx]
         };
-        if field.vis == hir::Public ||
-            (field.did.is_local() && self.private_accessible(field.did.node)) {
-            return
+        if field.vis == hir::Public || self.local_private_accessible(field.did) {
+            return;
         }
 
         let struct_desc = match def.adt_kind() {
@@ -726,19 +753,6 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                            span: Span,
                            method_id: DefId,
                            name: ast::Name) {
-        // If the method is a default method, we need to use the def_id of
-        // the default implementation.
-        let method_id = match self.tcx.impl_or_trait_item(method_id) {
-            ty::MethodTraitItem(method_type) => {
-                method_type.provided_source.unwrap_or(method_id)
-            }
-            _ => {
-                self.tcx.sess
-                    .span_bug(span,
-                              "got non-method item in check_static_method")
-            }
-        };
-
         self.report_error(self.ensure_public(span,
                                              method_id,
                                              None,
@@ -859,23 +873,6 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
 
 impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
     fn visit_item(&mut self, item: &hir::Item) {
-        if let hir::ItemUse(ref vpath) = item.node {
-            if let hir::ViewPathList(ref prefix, ref list) = vpath.node {
-                for pid in list {
-                    match pid.node {
-                        hir::PathListIdent { id, name, .. } => {
-                            debug!("privacy - ident item {}", id);
-                            self.check_path(pid.span, id, name.name);
-                        }
-                        hir::PathListMod { id, .. } => {
-                            debug!("privacy - mod item {}", id);
-                            let name = prefix.segments.last().unwrap().identifier.name;
-                            self.check_path(pid.span, id, name);
-                        }
-                    }
-                }
-            }
-        }
         let orig_curitem = replace(&mut self.curitem, item.id);
         visit::walk_item(self, item);
         self.curitem = orig_curitem;
@@ -883,12 +880,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
 
     fn visit_expr(&mut self, expr: &hir::Expr) {
         match expr.node {
-            hir::ExprField(ref base, ident) => {
+            hir::ExprField(ref base, name) => {
                 if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(&**base).sty {
                     self.check_field(expr.span,
                                      def,
                                      def.struct_variant(),
-                                     NamedField(ident.node.name));
+                                     NamedField(name.node));
                 }
             }
             hir::ExprTupField(ref base, idx) => {
@@ -899,11 +896,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
                                      UnnamedField(idx.node));
                 }
             }
-            hir::ExprMethodCall(ident, _, _) => {
+            hir::ExprMethodCall(name, _, _) => {
                 let method_call = ty::MethodCall::expr(expr.id);
                 let method = self.tcx.tables.borrow().method_map[&method_call];
                 debug!("(privacy checking) checking impl method");
-                self.check_method(expr.span, method.def_id, ident.node.name);
+                self.check_method(expr.span, method.def_id, name.node);
             }
             hir::ExprStruct(..) => {
                 let adt = self.tcx.expr_ty(expr).ty_adt_def().unwrap();
@@ -926,11 +923,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
                         _ => expr_ty
                     }.ty_adt_def().unwrap();
                     let any_priv = def.struct_variant().fields.iter().any(|f| {
-                        f.vis != hir::Public && (
-                            !f.did.is_local() ||
-                                    !self.private_accessible(f.did.node))
-                        });
-
+                        f.vis != hir::Public && !self.local_private_accessible(f.did)
+                    });
                     if any_priv {
                         span_err!(self.tcx.sess, expr.span, E0450,
                                   "cannot invoke tuple struct constructor with private \
@@ -958,7 +952,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
                 let variant = adt.variant_of_def(def);
                 for field in fields {
                     self.check_field(pattern.span, adt, variant,
-                                     NamedField(field.node.ident.name));
+                                     NamedField(field.node.name));
                 }
             }
 
@@ -997,8 +991,22 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
     }
 
     fn visit_path(&mut self, path: &hir::Path, id: ast::NodeId) {
-        self.check_path(path.span, id, path.segments.last().unwrap().identifier.name);
-        visit::walk_path(self, path);
+        if !path.segments.is_empty() {
+            self.check_path(path.span, id, path.segments.last().unwrap().identifier.name);
+            visit::walk_path(self, path);
+        }
+    }
+
+    fn visit_path_list_item(&mut self, prefix: &hir::Path, item: &hir::PathListItem) {
+        let name = if let hir::PathListIdent { name, .. } = item.node {
+            name
+        } else if !prefix.segments.is_empty() {
+            prefix.segments.last().unwrap().identifier.name
+        } else {
+            self.tcx.sess.bug("`self` import in an import list with empty prefix");
+        };
+        self.check_path(item.span, item.node.id(), name);
+        visit::walk_path_list_item(self, prefix, item);
     }
 }
 
@@ -1075,20 +1083,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
                                  instead");
             }
 
-            hir::ItemEnum(ref def, _) => {
-                for v in &def.variants {
-                    match v.node.vis {
-                        hir::Public => {
-                            if item.vis == hir::Public {
-                                span_err!(tcx.sess, v.span, E0448,
-                                          "unnecessary `pub` visibility");
-                            }
-                        }
-                        hir::Inherited => {}
-                    }
-                }
-            }
-
+            hir::ItemEnum(..) |
             hir::ItemTrait(..) | hir::ItemDefaultImpl(..) |
             hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemStruct(..) |
             hir::ItemFn(..) | hir::ItemMod(..) | hir::ItemTy(..) |
@@ -1106,8 +1101,8 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
                           "visibility has no effect inside functions");
             }
         }
-        let check_struct = |def: &hir::StructDef| {
-            for f in &def.fields {
+        let check_struct = |def: &hir::VariantData| {
+            for f in def.fields() {
                match f.node.kind {
                     hir::NamedField(_, p) => check_inherited(tcx, f.span, p),
                     hir::UnnamedField(..) => {}
@@ -1131,14 +1126,10 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
                     check_inherited(tcx, i.span, i.vis);
                 }
             }
-            hir::ItemEnum(ref def, _) => {
-                for v in &def.variants {
-                    check_inherited(tcx, v.span, v.node.vis);
-                }
-            }
 
-            hir::ItemStruct(ref def, _) => check_struct(&**def),
+            hir::ItemStruct(ref def, _) => check_struct(def),
 
+            hir::ItemEnum(..) |
             hir::ItemExternCrate(_) | hir::ItemUse(_) |
             hir::ItemTrait(..) | hir::ItemDefaultImpl(..) |
             hir::ItemStatic(..) | hir::ItemConst(..) |
@@ -1169,21 +1160,22 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
     fn path_is_private_type(&self, path_id: ast::NodeId) -> bool {
         let did = match self.tcx.def_map.borrow().get(&path_id).map(|d| d.full_def()) {
             // `int` etc. (None doesn't seem to occur.)
-            None | Some(def::DefPrimTy(..)) => return false,
+            None | Some(def::DefPrimTy(..)) | Some(def::DefSelfTy(..)) => return false,
             Some(def) => def.def_id(),
         };
+
         // A path can only be private if:
         // it's in this crate...
-        if !did.is_local() {
+        if let Some(node_id) = self.tcx.map.as_local_node_id(did) {
+            // .. and it corresponds to a private type in the AST (this returns
+            // None for type parameters)
+            match self.tcx.map.find(node_id) {
+                Some(ast_map::NodeItem(ref item)) => item.vis != hir::Public,
+                Some(_) | None => false,
+            }
+        } else {
             return false
         }
-
-        // .. and it corresponds to a private type in the AST (this returns
-        // None for type parameters)
-        match self.tcx.map.find(did.node) {
-            Some(ast_map::NodeItem(ref item)) => item.vis != hir::Public,
-            Some(_) | None => false,
-        }
     }
 
     fn trait_is_public(&self, trait_id: ast::NodeId) -> bool {
@@ -1283,7 +1275,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
                                               |tr| {
                         let did = self.tcx.trait_ref_to_def_id(tr);
 
-                        !did.is_local() || self.trait_is_public(did.node)
+                        if let Some(node_id) = self.tcx.map.as_local_node_id(did) {
+                            self.trait_is_public(node_id)
+                        } else {
+                            true // external traits must be public
+                        }
                     });
 
                 // `true` iff this is a trait impl or at least one method is public.
@@ -1447,20 +1443,20 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
         visit::walk_ty(self, t)
     }
 
-    fn visit_variant(&mut self, v: &hir::Variant, g: &hir::Generics) {
-        if self.exported_items.contains(&v.node.id) {
+    fn visit_variant(&mut self, v: &hir::Variant, g: &hir::Generics, item_id: ast::NodeId) {
+        if self.exported_items.contains(&v.node.data.id()) {
             self.in_variant = true;
-            visit::walk_variant(self, v, g);
+            visit::walk_variant(self, v, g, item_id);
             self.in_variant = false;
         }
     }
 
     fn visit_struct_field(&mut self, s: &hir::StructField) {
-        match s.node.kind {
-            hir::NamedField(_, vis) if vis == hir::Public || self.in_variant => {
-                visit::walk_struct_field(self, s);
-            }
-            _ => {}
+        let vis = match s.node.kind {
+            hir::NamedField(_, vis) | hir::UnnamedField(vis) => vis
+        };
+        if vis == hir::Public || self.in_variant {
+            visit::walk_struct_field(self, s);
         }
     }
 
index 6e72e51d9fefa3370180a4b1fc63184227ec872a..0bbceafa4a85ba8e47100f32d6ee4042f112ad49 100644 (file)
@@ -34,9 +34,10 @@ use self::NamespaceError::*;
 use rustc::metadata::csearch;
 use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
 use rustc::middle::def::*;
-use rustc::middle::def_id::DefId;
+use rustc::middle::def_id::{CRATE_DEF_INDEX, DefId};
 
 use syntax::ast::{Name, NodeId};
+use syntax::attr::AttrMetaMethods;
 use syntax::parse::token::special_idents;
 use syntax::codemap::{Span, DUMMY_SP};
 
@@ -48,12 +49,9 @@ use rustc_front::hir::{ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaul
 use rustc_front::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
 use rustc_front::hir::{NamedField, PathListIdent, PathListMod, Public};
 use rustc_front::hir::StmtDecl;
-use rustc_front::hir::StructVariantKind;
-use rustc_front::hir::TupleVariantKind;
 use rustc_front::hir::UnnamedField;
 use rustc_front::hir::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
 use rustc_front::hir::Visibility;
-use rustc_front::attr::AttrMetaMethods;
 use rustc_front::visit::{self, Visitor};
 
 use std::mem::replace;
@@ -263,7 +261,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
 
     /// Constructs the reduced graph for one item.
     fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) -> Rc<Module> {
-        let name = item.ident.name;
+        let name = item.name;
         let sp = item.span;
         let is_public = item.vis == hir::Public;
         let modifiers = if is_public {
@@ -281,14 +279,14 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                     ViewPathSimple(_, ref full_path) => {
                         full_path.segments
                             .split_last().unwrap().1
-                            .iter().map(|ident| ident.identifier.name)
+                            .iter().map(|seg| seg.identifier.name)
                             .collect()
                     }
 
                     ViewPathGlob(ref module_ident_path) |
                     ViewPathList(ref module_ident_path, _) => {
                         module_ident_path.segments
-                            .iter().map(|ident| ident.identifier.name).collect()
+                            .iter().map(|seg| seg.identifier.name).collect()
                     }
                 };
 
@@ -312,8 +310,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                                           ResolutionError::SelfImportsOnlyAllowedWithin);
                         }
 
-                        let subclass = SingleImport(binding.name,
-                                                    source_name);
+                        let subclass = SingleImport(binding, source_name);
                         self.build_import_directive(&**parent,
                                                     module_path,
                                                     subclass,
@@ -343,7 +340,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                         for source_item in source_items {
                             let (module_path, name, rename) = match source_item.node {
                                 PathListIdent { name, rename, .. } =>
-                                    (module_path.clone(), name.name, rename.unwrap_or(name).name),
+                                    (module_path.clone(), name, rename.unwrap_or(name)),
                                 PathListMod { rename, .. } => {
                                     let name = match module_path.last() {
                                         Some(name) => *name,
@@ -358,7 +355,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                                         }
                                     };
                                     let module_path = module_path.split_last().unwrap().1;
-                                    let rename = rename.map(|n| n.name).unwrap_or(name);
+                                    let rename = rename.unwrap_or(name);
                                     (module_path.to_vec(), name, rename)
                                 }
                             };
@@ -388,7 +385,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
             ItemExternCrate(_) => {
                 // n.b. we don't need to look at the path option here, because cstore already did
                 if let Some(crate_id) = self.session.cstore.find_extern_mod_stmt_cnum(item.id) {
-                    let def_id = DefId { krate: crate_id, node: 0 };
+                    let def_id = DefId { krate: crate_id, index: CRATE_DEF_INDEX };
                     self.external_exports.insert(def_id);
                     let parent_link = ModuleParentLink(Rc::downgrade(parent), name);
                     let external_module = Rc::new(Module::new(parent_link,
@@ -407,10 +404,33 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
             }
 
             ItemMod(..) => {
+                let child = parent.children.borrow().get(&name).cloned();
+                if let Some(child) = child {
+                    // check if there's struct of the same name already defined
+                    if child.defined_in_namespace(TypeNS)
+                        && child.get_module_if_available().is_none() {
+                        self.session.span_warn(sp, &format!(
+                                                    "duplicate definition of {} `{}`. \
+                                                     Defining a module and a struct with \
+                                                     the same name will be disallowed \
+                                                     soon.",
+                                               namespace_error_to_string(TypeError),
+                                               name));
+                        {
+                            let r = child.span_for_namespace(TypeNS);
+                            if let Some(sp) = r {
+                                self.session.span_note(sp,
+                                     &format!("first definition of {} `{}` here",
+                                          namespace_error_to_string(TypeError),
+                                          name));
+                            }
+                        }
+                    }
+                }
                 let name_bindings = self.add_child(name, parent, ForbidDuplicateModules, sp);
 
                 let parent_link = self.get_parent_link(parent, name);
-                let def_id = DefId { krate: 0, node: item.id };
+                let def_id = self.ast_map.local_def_id(item.id);
                 name_bindings.define_module(parent_link,
                                             Some(def_id),
                                             NormalModuleKind,
@@ -428,18 +448,20 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                 let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
                 let mutbl = m == hir::MutMutable;
 
-                name_bindings.define_value(DefStatic(DefId::local(item.id), mutbl), sp, modifiers);
+                name_bindings.define_value(DefStatic(self.ast_map.local_def_id(item.id), mutbl),
+                                           sp,
+                                           modifiers);
                 parent.clone()
             }
             ItemConst(_, _) => {
                 self.add_child(name, parent, ForbidDuplicateValues, sp)
-                    .define_value(DefConst(DefId::local(item.id)), sp, modifiers);
+                    .define_value(DefConst(self.ast_map.local_def_id(item.id)), sp, modifiers);
                 parent.clone()
             }
             ItemFn(_, _, _, _, _, _) => {
                 let name_bindings = self.add_child(name, parent, ForbidDuplicateValues, sp);
 
-                let def = DefFn(DefId::local(item.id), false);
+                let def = DefFn(self.ast_map.local_def_id(item.id), false);
                 name_bindings.define_value(def, sp, modifiers);
                 parent.clone()
             }
@@ -449,12 +471,12 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                 let name_bindings =
                     self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
 
-                name_bindings.define_type(DefTy(DefId::local(item.id), false), sp,
+                name_bindings.define_type(DefTy(self.ast_map.local_def_id(item.id), false), sp,
                                           modifiers);
 
                 let parent_link = self.get_parent_link(parent, name);
                 name_bindings.set_module_kind(parent_link,
-                                              Some(DefId::local(item.id)),
+                                              Some(self.ast_map.local_def_id(item.id)),
                                               TypeModuleKind,
                                               false,
                                               is_public,
@@ -466,11 +488,13 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                 let name_bindings =
                     self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
 
-                name_bindings.define_type(DefTy(DefId::local(item.id), true), sp, modifiers);
+                name_bindings.define_type(DefTy(self.ast_map.local_def_id(item.id), true),
+                                          sp,
+                                          modifiers);
 
                 let parent_link = self.get_parent_link(parent, name);
                 name_bindings.set_module_kind(parent_link,
-                                              Some(DefId::local(item.id)),
+                                              Some(self.ast_map.local_def_id(item.id)),
                                               EnumModuleKind,
                                               false,
                                               is_public,
@@ -479,9 +503,10 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                 let module = name_bindings.get_module();
 
                 for variant in &(*enum_definition).variants {
+                    let item_def_id = self.ast_map.local_def_id(item.id);
                     self.build_reduced_graph_for_variant(
                         &**variant,
-                        DefId::local(item.id),
+                        item_def_id,
                         &module);
                 }
                 parent.clone()
@@ -490,30 +515,58 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
             // These items live in both the type and value namespaces.
             ItemStruct(ref struct_def, _) => {
                 // Adding to both Type and Value namespaces or just Type?
-                let (forbid, ctor_id) = match struct_def.ctor_id {
-                    Some(ctor_id)   => (ForbidDuplicateTypesAndValues, Some(ctor_id)),
-                    None            => (ForbidDuplicateTypesAndModules, None)
+                let (forbid, ctor_id) = if struct_def.is_struct() {
+                    (ForbidDuplicateTypesAndModules, None)
+                } else {
+                    let child = parent.children.borrow().get(&name).cloned();
+                    if let Some(child) = child {
+                        // check if theres a DefMod
+                        if let Some(DefMod(_)) = child.def_for_namespace(TypeNS) {
+                            self.session.span_warn(sp, &format!(
+                                                        "duplicate definition of {} `{}`. \
+                                                         Defining a module and a struct with \
+                                                         the same name will be disallowed \
+                                                         soon.",
+                                                   namespace_error_to_string(TypeError),
+                                                   name));
+                            {
+                                let r = child.span_for_namespace(TypeNS);
+                                if let Some(sp) = r {
+                                    self.session.span_note(sp,
+                                         &format!("first definition of {} `{}` here",
+                                              namespace_error_to_string(TypeError),
+                                              name));
+                                }
+                            }
+                        }
+                    }
+                    (ForbidDuplicateTypesAndValues, Some(struct_def.id()))
                 };
 
                 let name_bindings = self.add_child(name, parent, forbid, sp);
 
                 // Define a name in the type namespace.
-                name_bindings.define_type(DefTy(DefId::local(item.id), false), sp, modifiers);
+                name_bindings.define_type(DefTy(self.ast_map.local_def_id(item.id), false),
+                                          sp,
+                                          modifiers);
 
                 // If this is a newtype or unit-like struct, define a name
                 // in the value namespace as well
                 if let Some(cid) = ctor_id {
-                    name_bindings.define_value(DefStruct(DefId::local(cid)), sp, modifiers);
+                    name_bindings.define_value(DefStruct(self.ast_map.local_def_id(cid)),
+                                               sp,
+                                               modifiers);
                 }
 
                 // Record the def ID and fields of this struct.
-                let named_fields = struct_def.fields.iter().filter_map(|f| {
+                let named_fields = struct_def.fields().iter().filter_map(|f| {
                     match f.node.kind {
-                        NamedField(ident, _) => Some(ident.name),
+                        NamedField(name, _) => Some(name),
                         UnnamedField(_) => None
                     }
                 }).collect();
-                self.structs.insert(DefId::local(item.id), named_fields);
+                let item_def_id = self.ast_map.local_def_id(item.id);
+                self.structs.insert(item_def_id, named_fields);
 
                 parent.clone()
             }
@@ -528,43 +581,43 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                 // Add all the items within to a new module.
                 let parent_link = self.get_parent_link(parent, name);
                 name_bindings.define_module(parent_link,
-                                            Some(DefId::local(item.id)),
+                                            Some(self.ast_map.local_def_id(item.id)),
                                             TraitModuleKind,
                                             false,
                                             is_public,
                                             sp);
                 let module_parent = name_bindings.get_module();
 
-                let def_id = DefId::local(item.id);
+                let def_id = self.ast_map.local_def_id(item.id);
 
                 // Add the names of all the items to the trait info.
                 for trait_item in items {
-                    let name_bindings = self.add_child(trait_item.ident.name,
+                    let name_bindings = self.add_child(trait_item.name,
                                         &module_parent,
                                         ForbidDuplicateTypesAndValues,
                                         trait_item.span);
 
                     match trait_item.node {
                         hir::ConstTraitItem(..) => {
-                            let def = DefAssociatedConst(DefId::local(trait_item.id));
+                            let def = DefAssociatedConst(self.ast_map.local_def_id(trait_item.id));
                             // NB: not DefModifiers::IMPORTABLE
                             name_bindings.define_value(def, trait_item.span, DefModifiers::PUBLIC);
                         }
                         hir::MethodTraitItem(..) => {
-                            let def = DefMethod(DefId::local(trait_item.id));
+                            let def = DefMethod(self.ast_map.local_def_id(trait_item.id));
                             // NB: not DefModifiers::IMPORTABLE
                             name_bindings.define_value(def, trait_item.span, DefModifiers::PUBLIC);
                         }
                         hir::TypeTraitItem(..) => {
-                            let def = DefAssociatedTy(DefId::local(item.id),
-                                                      DefId::local(trait_item.id));
+                            let def = DefAssociatedTy(self.ast_map.local_def_id(item.id),
+                                                      self.ast_map.local_def_id(trait_item.id));
                             // NB: not DefModifiers::IMPORTABLE
                             name_bindings.define_type(def, trait_item.span, DefModifiers::PUBLIC);
                         }
                     }
 
-                    self.trait_item_map.insert((trait_item.ident.name, def_id),
-                                               DefId::local(trait_item.id));
+                    let trait_item_def_id = self.ast_map.local_def_id(trait_item.id);
+                    self.trait_item_map.insert((trait_item.name, def_id), trait_item_def_id);
                 }
 
                 name_bindings.define_type(DefTrait(def_id), sp, modifiers);
@@ -579,14 +632,14 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
                                        variant: &Variant,
                                        item_id: DefId,
                                        parent: &Rc<Module>) {
-        let name = variant.node.name.name;
-        let is_exported = match variant.node.kind {
-            TupleVariantKind(_) => false,
-            StructVariantKind(_) => {
-                // Not adding fields for variants as they are not accessed with a self receiver
-                self.structs.insert(DefId::local(variant.node.id), Vec::new());
-                true
-            }
+        let name = variant.node.name;
+        let is_exported = if variant.node.data.is_struct() {
+            // Not adding fields for variants as they are not accessed with a self receiver
+            let variant_def_id = self.ast_map.local_def_id(variant.node.data.id());
+            self.structs.insert(variant_def_id, Vec::new());
+            true
+        } else {
+            false
         };
 
         let child = self.add_child(name, parent,
@@ -595,10 +648,12 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
         // variants are always treated as importable to allow them to be glob
         // used
         child.define_value(DefVariant(item_id,
-                                      DefId::local(variant.node.id), is_exported),
+                                      self.ast_map.local_def_id(variant.node.data.id()),
+                                      is_exported),
                            variant.span, DefModifiers::PUBLIC | DefModifiers::IMPORTABLE);
         child.define_type(DefVariant(item_id,
-                                     DefId::local(variant.node.id), is_exported),
+                                     self.ast_map.local_def_id(variant.node.data.id()),
+                                     is_exported),
                           variant.span, DefModifiers::PUBLIC | DefModifiers::IMPORTABLE);
     }
 
@@ -606,7 +661,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
     fn build_reduced_graph_for_foreign_item(&mut self,
                                             foreign_item: &ForeignItem,
                                             parent: &Rc<Module>) {
-        let name = foreign_item.ident.name;
+        let name = foreign_item.name;
         let is_public = foreign_item.vis == hir::Public;
         let modifiers = if is_public {
             DefModifiers::PUBLIC
@@ -619,10 +674,10 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
 
         let def = match foreign_item.node {
             ForeignItemFn(..) => {
-                DefFn(DefId::local(foreign_item.id), false)
+                DefFn(self.ast_map.local_def_id(foreign_item.id), false)
             }
             ForeignItemStatic(_, m) => {
-                DefStatic(DefId::local(foreign_item.id), m)
+                DefStatic(self.ast_map.local_def_id(foreign_item.id), m)
             }
         };
         name_bindings.define_value(def, foreign_item.span, modifiers);
@@ -806,7 +861,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
             self.structs.insert(def_id, fields);
           }
           DefLocal(..) | DefPrimTy(..) | DefTyParam(..) |
-          DefUse(..) | DefUpvar(..) | DefRegion(..) |
+          DefUse(..) | DefUpvar(..) |
           DefLabel(..) | DefSelfTy(..) => {
             panic!("didn't expect `{:?}`", def);
           }
index f06fd9f70e2c1f1e118b842e3c6d60f601bbd9af..4147f2bea48509c6eacbb2cfbf24307034a203f9 100644 (file)
@@ -609,6 +609,29 @@ match Something::NotFoo {
 ```
 "##,
 
+E0422: r##"
+You are trying to use an identifier that is either undefined or not a
+struct. For instance:
+```
+fn main () {
+    let x = Foo { x: 1, y: 2 };
+}
+```
+
+In this case, `Foo` is undefined, so it inherently isn't anything, and
+definitely not a struct.
+
+```
+fn main () {
+    let foo = 1;
+    let x = foo { x: 1, y: 2 };
+}
+```
+
+In this case, `foo` is defined, but is not a struct, so Rust can't use
+it as one.
+"##,
+
 E0423: r##"
 A `struct` variant name was used like a function name. Example of
 erroneous code:
@@ -888,7 +911,6 @@ register_diagnostics! {
     E0418, // is not an enum variant, struct or const
     E0420, // is not an associated const
     E0421, // unresolved associated const
-    E0422, // does not name a structure
     E0427, // cannot use `ref` binding mode with ...
     E0429, // `self` imports are only allowed within a { } list
     E0434, // can't capture dynamic environment in a fn item
index 79aa4e535220ee1925c5848e55f153fc6456f0f1..106591724a79812f8af3d83fb8c2a91bb250b357 100644 (file)
@@ -23,7 +23,6 @@
 #![feature(borrow_state)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
-#![feature(slice_splits)]
 #![feature(staged_api)]
 
 #[macro_use] extern crate log;
@@ -57,7 +56,7 @@ use rustc::metadata::csearch;
 use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
 use rustc::middle::def::*;
 use rustc::middle::def_id::DefId;
-use rustc::middle::pat_util::pat_bindings;
+use rustc::middle::pat_util::pat_bindings_hygienic;
 use rustc::middle::privacy::*;
 use rustc::middle::subst::{ParamSpace, FnSpace, TypeSpace};
 use rustc::middle::ty::{Freevar, FreevarMap, TraitMap, GlobMap};
@@ -65,7 +64,8 @@ use rustc::util::nodemap::{NodeMap, DefIdSet, FnvHashMap};
 use rustc::util::lev_distance::lev_distance;
 
 use syntax::ast;
-use syntax::ast::{Ident, Name, NodeId, CrateNum};
+use syntax::ast::{CRATE_NODE_ID, Ident, Name, NodeId, CrateNum, TyIs, TyI8, TyI16, TyI32, TyI64};
+use syntax::ast::{TyUs, TyU8, TyU16, TyU32, TyU64, TyF64, TyF32};
 use syntax::attr::AttrMetaMethods;
 use syntax::ext::mtwt;
 use syntax::parse::token::{self, special_names, special_idents};
@@ -86,10 +86,8 @@ use rustc_front::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
 use rustc_front::hir::{Local, MethodImplItem};
 use rustc_front::hir::{Pat, PatEnum, PatIdent, PatLit, PatQPath};
 use rustc_front::hir::{PatRange, PatStruct, Path, PrimTy};
-use rustc_front::hir::{TraitRef, Ty, TyBool, TyChar, TyF32};
-use rustc_front::hir::{TyF64, TyFloat, TyIs, TyI8, TyI16, TyI32, TyI64, TyInt};
-use rustc_front::hir::{TyPath, TyPtr};
-use rustc_front::hir::{TyRptr, TyStr, TyUs, TyU8, TyU16, TyU32, TyU64, TyUint};
+use rustc_front::hir::{TraitRef, Ty, TyBool, TyChar, TyFloat, TyInt};
+use rustc_front::hir::{TyRptr, TyStr, TyUint, TyPath, TyPtr};
 use rustc_front::hir::TypeImplItem;
 use rustc_front::util::walk_pat;
 
@@ -492,7 +490,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
         }
         visit::walk_poly_trait_ref(self, tref, m);
     }
-    fn visit_variant(&mut self, variant: &hir::Variant, generics: &Generics) {
+    fn visit_variant(&mut self, variant: &hir::Variant, generics: &Generics, item_id: ast::NodeId) {
         execute_callback!(hir_map::Node::NodeVariant(variant), self);
         if let Some(ref dis_expr) = variant.node.disr_expr {
             // resolve the discriminator expr as a constant
@@ -502,19 +500,8 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
         }
 
         // `visit::walk_variant` without the discriminant expression.
-        match variant.node.kind {
-            hir::TupleVariantKind(ref variant_arguments) => {
-                for variant_argument in variant_arguments {
-                    self.visit_ty(&*variant_argument.ty);
-                }
-            }
-            hir::StructVariantKind(ref struct_definition) => {
-                self.visit_struct_def(&**struct_definition,
-                                      variant.node.name,
-                                      generics,
-                                      variant.node.id);
-            }
-        }
+        self.visit_variant_data(&variant.node.data, variant.node.name,
+                              generics, item_id, variant.span);
     }
     fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem) {
         execute_callback!(hir_map::Node::NodeForeignItem(foreign_item), self);
@@ -1189,8 +1176,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
            make_glob_map: MakeGlobMap) -> Resolver<'a, 'tcx> {
         let graph_root = NameBindings::new();
 
+        let root_def_id = ast_map.local_def_id(CRATE_NODE_ID);
         graph_root.define_module(NoParentLink,
-                                 Some(DefId { krate: 0, node: 0 }),
+                                 Some(root_def_id),
                                  NormalModuleKind,
                                  false,
                                  true,
@@ -1258,8 +1246,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     }
 
     fn get_trait_name(&self, did: DefId) -> Name {
-        if did.is_local() {
-            self.ast_map.expect_item(did.node).ident.name
+        if let Some(node_id) = self.ast_map.as_local_node_id(did) {
+            self.ast_map.expect_item(node_id).name
         } else {
             csearch::get_trait_name(&self.session.cstore, did)
         }
@@ -1982,7 +1970,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 self.session.span_bug(span,
                     &format!("unexpected {:?} in bindings", def))
             }
-            DefLocal(node_id) => {
+            DefLocal(_, node_id) => {
                 for rib in ribs {
                     match rib.kind {
                         NormalRibKind => {
@@ -1990,11 +1978,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         }
                         ClosureRibKind(function_id) => {
                             let prev_def = def;
+                            let node_def_id = self.ast_map.local_def_id(node_id);
 
                             let mut seen = self.freevars_seen.borrow_mut();
                             let seen = seen.entry(function_id).or_insert_with(|| NodeMap());
                             if let Some(&index) = seen.get(&node_id) {
-                                def = DefUpvar(node_id, index, function_id);
+                                def = DefUpvar(node_def_id, node_id, index, function_id);
                                 continue;
                             }
                             let mut freevars = self.freevars.borrow_mut();
@@ -2003,7 +1992,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             let depth = vec.len();
                             vec.push(Freevar { def: prev_def, span: span });
 
-                            def = DefUpvar(node_id, depth, function_id);
+                            def = DefUpvar(node_def_id, node_id, depth, function_id);
                             seen.insert(node_id, depth);
                         }
                         ItemRibKind | MethodRibKind => {
@@ -2110,7 +2099,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     }
 
     fn resolve_item(&mut self, item: &Item) {
-        let name = item.ident.name;
+        let name = item.name;
 
         debug!("(resolving item) resolving {}",
                name);
@@ -2157,9 +2146,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                                                TypeSpace,
                                                                ItemRibKind),
                                              |this| {
-                    this.with_self_rib(DefSelfTy(Some(DefId::local(item.id)), None), |this| {
+                    let local_def_id = this.ast_map.local_def_id(item.id);
+                    this.with_self_rib(DefSelfTy(Some(local_def_id), None), |this| {
                         this.visit_generics(generics);
-                        visit::walk_ty_param_bounds_helper(this, bounds);
+                        walk_list!(this, visit_ty_param_bound, bounds);
 
                         for trait_item in trait_items {
                             match trait_item.node {
@@ -2185,7 +2175,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                     });
                                 }
                                 hir::TypeTraitItem(..) => {
-                                    this.check_if_primitive_type_name(trait_item.ident.name,
+                                    this.check_if_primitive_type_name(trait_item.name,
                                                                       trait_item.span);
                                     this.with_type_parameter_rib(NoTypeParameters, |this| {
                                         visit::walk_trait_item(this, trait_item)
@@ -2211,23 +2201,39 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
             ItemUse(ref view_path) => {
                 // check for imports shadowing primitive types
-                let check_rename = |id, ident: Ident| {
-                    match self.def_map.borrow().get(&id).map(|d| d.full_def()) {
+                let check_rename = |this: &Self, id, name| {
+                    match this.def_map.borrow().get(&id).map(|d| d.full_def()) {
                         Some(DefTy(..)) | Some(DefStruct(..)) | Some(DefTrait(..)) | None => {
-                            self.check_if_primitive_type_name(ident.name, item.span);
+                            this.check_if_primitive_type_name(name, item.span);
                         }
                         _ => {}
                     }
                 };
 
                 match view_path.node {
-                    hir::ViewPathSimple(ident, _) => {
-                        check_rename(item.id, ident);
+                    hir::ViewPathSimple(name, _) => {
+                        check_rename(self, item.id, name);
                     }
-                    hir::ViewPathList(_, ref items) => {
+                    hir::ViewPathList(ref prefix, ref items) => {
                         for item in items {
-                            if let Some(ident) = item.node.rename() {
-                                check_rename(item.node.id(), ident);
+                            if let Some(name) = item.node.rename() {
+                                check_rename(self, item.node.id(), name);
+                            }
+                        }
+
+                        // Resolve prefix of an import with empty braces (issue #28388)
+                        if items.is_empty() && !prefix.segments.is_empty() {
+                            match self.resolve_crate_relative_path(prefix.span,
+                                                                   &prefix.segments,
+                                                                   TypeNS) {
+                                Some((def, lp)) => self.record_def(item.id,
+                                                   PathResolution::new(def, lp, 0)),
+                                None => {
+                                    resolve_error(self,
+                                                  prefix.span,
+                                                  ResolutionError::FailedToResolve(
+                                                      &path_names_to_string(prefix, 0)));
+                                }
                             }
                         }
                     }
@@ -2249,7 +2255,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 let mut function_type_rib = Rib::new(rib_kind);
                 let mut seen_bindings = HashSet::new();
                 for (index, type_parameter) in generics.ty_params.iter().enumerate() {
-                    let name = type_parameter.ident.name;
+                    let name = type_parameter.name;
                     debug!("with_type_parameter_rib: {}", type_parameter.id);
 
                     if seen_bindings.contains(&name) {
@@ -2265,7 +2271,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     function_type_rib.bindings.insert(name,
                         DlDef(DefTyParam(space,
                                          index as u32,
-                                         DefId::local(type_parameter.id),
+                                         self.ast_map.local_def_id(type_parameter.id),
                                          name)));
                 }
                 self.type_ribs.push(function_type_rib);
@@ -2375,7 +2381,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
     fn resolve_generics(&mut self, generics: &Generics) {
         for type_parameter in generics.ty_params.iter() {
-            self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span);
+            self.check_if_primitive_type_name(type_parameter.name, type_parameter.span);
         }
         for predicate in &generics.where_clause.predicates {
             match predicate {
@@ -2471,7 +2477,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                 ConstImplItem(..) => {
                                     // If this is a trait impl, ensure the const
                                     // exists in trait
-                                    this.check_trait_item(impl_item.ident.name,
+                                    this.check_trait_item(impl_item.name,
                                                           impl_item.span,
                                         |n, s| ResolutionError::ConstNotMemberOfTrait(n, s));
                                     this.with_constant_rib(|this| {
@@ -2481,7 +2487,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                 MethodImplItem(ref sig, _) => {
                                     // If this is a trait impl, ensure the method
                                     // exists in trait
-                                    this.check_trait_item(impl_item.ident.name,
+                                    this.check_trait_item(impl_item.name,
                                                           impl_item.span,
                                         |n, s| ResolutionError::MethodNotMemberOfTrait(n, s));
 
@@ -2498,7 +2504,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                 TypeImplItem(ref ty) => {
                                     // If this is a trait impl, ensure the type
                                     // exists in trait
-                                    this.check_trait_item(impl_item.ident.name,
+                                    this.check_trait_item(impl_item.name,
                                                           impl_item.span,
                                         |n, s| ResolutionError::TypeNotMemberOfTrait(n, s));
 
@@ -2527,10 +2533,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
     fn resolve_local(&mut self, local: &Local) {
         // Resolve the type.
-        visit::walk_ty_opt(self, &local.ty);
+        walk_list!(self, visit_ty, &local.ty);
 
         // Resolve the initializer.
-        visit::walk_expr_opt(self, &local.init);
+        walk_list!(self, visit_expr, &local.init);
 
         // Resolve the pattern.
         self.resolve_pattern(&*local.pat,
@@ -2544,7 +2550,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
     // user and one 'x' came from the macro.
     fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap {
         let mut result = HashMap::new();
-        pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path1| {
+        pat_bindings_hygienic(&self.def_map, pat, |binding_mode, _id, sp, path1| {
             let name = mtwt::resolve(path1.node);
             result.insert(name, BindingInfo {
                 span: sp,
@@ -2607,7 +2613,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         // pat_idents are variants
         self.check_consistent_bindings(arm);
 
-        visit::walk_expr_opt(self, &arm.guard);
+        walk_list!(self, visit_expr, &arm.guard);
         self.visit_expr(&*arm.body);
 
         if !self.resolved {
@@ -2800,7 +2806,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             debug!("(resolving pattern) binding `{}`",
                                    renamed);
 
-                            let def = DefLocal(pattern.id);
+                            let def_id = self.ast_map.local_def_id(pattern.id);
+                            let def = DefLocal(def_id, pattern.id);
 
                             // Record the definition so that later passes
                             // will be able to distinguish variants from
@@ -3482,8 +3489,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         }
 
         fn is_static_method(this: &Resolver, did: DefId) -> bool {
-            if did.is_local() {
-                let sig = match this.ast_map.get(did.node) {
+            if let Some(node_id) = this.ast_map.as_local_node_id(did) {
+                let sig = match this.ast_map.get(node_id) {
                     hir_map::NodeTraitItem(trait_item) => match trait_item.node {
                         hir::MethodTraitItem(ref sig, _) => sig,
                         _ => return false
@@ -3695,7 +3702,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                 false // Stop advancing
                             });
 
-                            if method_scope && special_names::self_ == path_name {
+                            if method_scope && special_names::self_.as_str() == &path_name[..] {
                                 resolve_error(
                                     self,
                                     expr.span,
@@ -3802,19 +3809,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
 
     fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) {
         match expr.node {
-            ExprField(_, ident) => {
+            ExprField(_, name) => {
                 // FIXME(#6890): Even though you can't treat a method like a
                 // field, we need to add any trait methods we find that match
                 // the field name so that we can do some nice error reporting
                 // later on in typeck.
-                let traits = self.get_traits_containing_item(ident.node.name);
+                let traits = self.get_traits_containing_item(name.node);
                 self.trait_map.insert(expr.id, traits);
             }
-            ExprMethodCall(ident, _, _) => {
+            ExprMethodCall(name, _, _) => {
                 debug!("(recording candidate traits for expr) recording \
                         traits for {}",
                        expr.id);
-                let traits = self.get_traits_containing_item(ident.node.name);
+                let traits = self.get_traits_containing_item(name.node);
                 self.trait_map.insert(expr.id, traits);
             }
             _ => {
@@ -3830,9 +3837,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         fn add_trait_info(found_traits: &mut Vec<DefId>,
                           trait_def_id: DefId,
                           name: Name) {
-            debug!("(adding trait info) found trait {}:{} for method '{}'",
-                trait_def_id.krate,
-                trait_def_id.node,
+            debug!("(adding trait info) found trait {:?} for method '{}'",
+                trait_def_id,
                 name);
             found_traits.push(trait_def_id);
         }
index 36ed2c1457954dc665a806915ec3ed1ff7068acc..0eb1e2cc06f613c2b550d8abc9c7bcda03de404d 100644 (file)
@@ -102,9 +102,9 @@ impl<'a, 'b, 'tcx> ExportRecorder<'a, 'b, 'tcx> {
         self.add_exports_for_module(&mut exports, module_);
         match module_.def_id.get() {
             Some(def_id) => {
-                self.export_map.insert(def_id.node, exports);
-                debug!("(computing exports) writing exports for {} (some)",
-                       def_id.node);
+                let node_id = self.ast_map.as_local_node_id(def_id).unwrap();
+                self.export_map.insert(node_id, exports);
+                debug!("(computing exports) writing exports for {} (some)", node_id);
             }
             None => {}
         }
index 3c2612a1348559f8fec49c96bc60eefddc00e832..99d7685f7c8f290dbd770a4685fdecdfb172f3f7 100644 (file)
@@ -537,7 +537,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                         fn get_binding(this: &mut Resolver,
                                        import_resolution: &ImportResolution,
                                        namespace: Namespace,
-                                       source: &Name)
+                                       source: Name)
                                     -> NamespaceResult {
 
                             // Import resolutions must be declared with "pub"
@@ -560,7 +560,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                                     let id = import_resolution.id(namespace);
                                     // track used imports and extern crates as well
                                     this.used_imports.insert((id, namespace));
-                                    this.record_import_use(id, *source);
+                                    this.record_import_use(id, source);
                                     match target_module.def_id.get() {
                                         Some(DefId{krate: kid, ..}) => {
                                             this.used_crates.insert(kid);
@@ -578,14 +578,14 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                             value_result = get_binding(self.resolver,
                                                        import_resolution,
                                                        ValueNS,
-                                                       &source);
+                                                       source);
                             value_used_reexport = import_resolution.is_public;
                         }
                         if type_result.is_unknown() {
                             type_result = get_binding(self.resolver,
                                                       import_resolution,
                                                       TypeNS,
-                                                      &source);
+                                                      source);
                             type_used_reexport = import_resolution.is_public;
                         }
 
@@ -793,10 +793,10 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                     )));
         }
 
-        for (ident, target_import_resolution) in import_resolutions.iter() {
+        for (name, target_import_resolution) in import_resolutions.iter() {
             debug!("(resolving glob import) writing module resolution \
                     {} into `{}`",
-                   *ident,
+                   *name,
                    module_to_string(module_));
 
             if !target_import_resolution.is_public {
@@ -806,7 +806,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
 
             // Here we merge two import resolutions.
             let mut import_resolutions = module_.import_resolutions.borrow_mut();
-            match import_resolutions.get_mut(ident) {
+            match import_resolutions.get_mut(name) {
                 Some(dest_import_resolution) => {
                     // Merge the two import resolutions at a finer-grained
                     // level.
@@ -818,7 +818,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                         Some(ref value_target) => {
                             self.check_for_conflicting_import(&dest_import_resolution,
                                                               import_directive.span,
-                                                              *ident,
+                                                              *name,
                                                               ValueNS);
                             dest_import_resolution.value_target = Some(value_target.clone());
                         }
@@ -830,7 +830,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
                         Some(ref type_target) => {
                             self.check_for_conflicting_import(&dest_import_resolution,
                                                               import_directive.span,
-                                                              *ident,
+                                                              *name,
                                                               TypeNS);
                             dest_import_resolution.type_target = Some(type_target.clone());
                         }
@@ -848,7 +848,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
             new_import_resolution.type_target =
                 target_import_resolution.type_target.clone();
 
-            import_resolutions.insert(*ident, new_import_resolution);
+            import_resolutions.insert(*name, new_import_resolution);
         }
 
         // Add all children from the containing module.
index 76bbce00f19dc3be0b91ea2f401801461b873162..1b3242eb97d33caafacfb0b38aea31c07ed83ae8 100644 (file)
@@ -145,10 +145,13 @@ impl<'a> ArchiveBuilder<'a> {
 
     /// Adds all of the contents of a native library to this archive. This will
     /// search in the relevant locations for a library named `name`.
-    pub fn add_native_library(&mut self, name: &str) -> io::Result<()> {
+    pub fn add_native_library(&mut self, name: &str) {
         let location = find_library(name, &self.config.lib_search_paths,
                                     self.config.sess);
-        self.add_archive(&location, name, |_| false)
+        self.add_archive(&location, name, |_| false).unwrap_or_else(|e| {
+            self.config.sess.fatal(&format!("failed to add native library {}: {}",
+                                            location.to_string_lossy(), e));
+        });
     }
 
     /// Adds all of the contents of the rlib at the specified path to this
index d5486e84fc43123fc8bdbe99f94931f1e581af71..6171ff1382fbd4bda2e04d80b9803e4e7fc96141 100644 (file)
@@ -16,7 +16,7 @@ use super::msvc;
 use super::svh::Svh;
 use session::config;
 use session::config::NoDebugInfo;
-use session::config::{OutputFilenames, Input, OutputTypeBitcode, OutputTypeExe, OutputTypeObject};
+use session::config::{OutputFilenames, Input, OutputType};
 use session::search_paths::PathKind;
 use session::Session;
 use metadata::common::LinkMeta;
@@ -25,17 +25,20 @@ use metadata::loader::METADATA_FILENAME;
 use metadata::{encoder, cstore, filesearch, csearch, creader};
 use middle::dependency_format::Linkage;
 use middle::ty::{self, Ty};
-use rustc::front::map::{PathElem, PathElems, PathName};
+use rustc::front::map::DefPath;
 use trans::{CrateContext, CrateTranslation, gensym_name};
 use util::common::time;
 use util::sha2::{Digest, Sha256};
 use util::fs::fix_windows_verbatim_for_gcc;
 use rustc_back::tempdir::TempDir;
 
+use std::ascii;
+use std::char;
 use std::env;
 use std::ffi::OsString;
-use std::fs::{self, PathExt};
+use std::fs;
 use std::io::{self, Read, Write};
+use std::iter::once;
 use std::mem;
 use std::path::{Path, PathBuf};
 use std::process::Command;
@@ -44,9 +47,8 @@ use flate;
 use serialize::hex::ToHex;
 use syntax::ast;
 use syntax::codemap::Span;
-use syntax::parse::token;
+use syntax::parse::token::{self, InternedString};
 use syntax::attr::AttrMetaMethods;
-use rustc_front::attr::AttrMetaMethods as FrontAttrMetaMethods;
 
 use rustc_front::hir;
 
@@ -182,9 +184,9 @@ pub fn find_crate_name(sess: Option<&Session>,
 }
 
 pub fn build_link_meta(sess: &Session, krate: &hir::Crate,
-                       name: String) -> LinkMeta {
+                       name: &str) -> LinkMeta {
     let r = LinkMeta {
-        crate_name: name,
+        crate_name: name.to_owned(),
         crate_hash: Svh::calculate(&sess.opts.cg.metadata, krate),
     };
     info!("{:?}", r);
@@ -215,7 +217,7 @@ fn symbol_hash<'tcx>(tcx: &ty::ctxt<'tcx>,
         symbol_hasher.input_str(&meta[..]);
     }
     symbol_hasher.input_str("-");
-    symbol_hasher.input_str(&encoder::encoded_ty(tcx, t));
+    symbol_hasher.input(&encoder::encoded_ty(tcx, t));
     // Prefix with 'h' so that it never blends into adjacent digits
     let mut hash = String::from("h");
     hash.push_str(&truncated_hash_result(symbol_hasher));
@@ -285,8 +287,7 @@ pub fn sanitize(s: &str) -> String {
     return result;
 }
 
-pub fn mangle<PI: Iterator<Item=PathElem>>(path: PI,
-                                           hash: Option<&str>) -> String {
+pub fn mangle<PI: Iterator<Item=InternedString>>(path: PI, hash: Option<&str>) -> String {
     // Follow C++ namespace-mangling style, see
     // http://en.wikipedia.org/wiki/Name_mangling for more info.
     //
@@ -309,8 +310,8 @@ pub fn mangle<PI: Iterator<Item=PathElem>>(path: PI,
     }
 
     // First, connect each component with <len, name> pairs.
-    for e in path {
-        push(&mut n, &e.name().as_str())
+    for data in path {
+        push(&mut n, &data);
     }
 
     match hash {
@@ -322,11 +323,13 @@ pub fn mangle<PI: Iterator<Item=PathElem>>(path: PI,
     n
 }
 
-pub fn exported_name(path: PathElems, hash: &str) -> String {
+pub fn exported_name(path: DefPath, hash: &str) -> String {
+    let path = path.into_iter()
+                   .map(|e| e.data.as_interned_str());
     mangle(path, Some(hash))
 }
 
-pub fn mangle_exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, path: PathElems,
+pub fn mangle_exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, path: DefPath,
                                       t: Ty<'tcx>, id: ast::NodeId) -> String {
     let mut hash = get_symbol_hash(ccx, t);
 
@@ -354,14 +357,17 @@ pub fn mangle_exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, path: PathEl
 pub fn mangle_internal_name_by_type_and_seq<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                                       t: Ty<'tcx>,
                                                       name: &str) -> String {
-    let path = [PathName(token::intern(&t.to_string())),
-                gensym_name(name)];
+    let path = [token::intern(&t.to_string()).as_str(), gensym_name(name).as_str()];
     let hash = get_symbol_hash(ccx, t);
     mangle(path.iter().cloned(), Some(&hash[..]))
 }
 
-pub fn mangle_internal_name_by_path_and_seq(path: PathElems, flav: &str) -> String {
-    mangle(path.chain(Some(gensym_name(flav))), None)
+pub fn mangle_internal_name_by_path_and_seq(path: DefPath, flav: &str) -> String {
+    let names =
+        path.into_iter()
+            .map(|e| e.data.as_interned_str())
+            .chain(once(gensym_name(flav).as_str())); // append unique version of "flav"
+    mangle(names, None)
 }
 
 pub fn get_linker(sess: &Session) -> (String, Command) {
@@ -487,7 +493,7 @@ pub fn filename_for_input(sess: &Session,
         }
         config::CrateTypeExecutable => {
             let suffix = &sess.target.target.options.exe_suffix;
-            let out_filename = outputs.path(OutputTypeExe);
+            let out_filename = outputs.path(OutputType::Exe);
             if suffix.is_empty() {
                 out_filename.to_path_buf()
             } else {
@@ -528,10 +534,12 @@ fn link_binary_output(sess: &Session,
                       outputs: &OutputFilenames,
                       crate_name: &str) -> PathBuf {
     let objects = object_filenames(sess, outputs);
-    let out_filename = match outputs.single_output_file {
-        Some(ref file) => file.clone(),
-        None => filename_for_input(sess, crate_type, crate_name, outputs),
-    };
+    let default_filename = filename_for_input(sess, crate_type, crate_name,
+                                              outputs);
+    let out_filename = outputs.outputs.get(&OutputType::Exe)
+                              .and_then(|s| s.to_owned())
+                              .or_else(|| outputs.single_output_file.clone())
+                              .unwrap_or(default_filename);
 
     // Make sure files are writeable.  Mac, FreeBSD, and Windows system linkers
     // check this already -- however, the Linux linker will happily overwrite a
@@ -543,7 +551,11 @@ fn link_binary_output(sess: &Session,
         }
     }
 
-    let tmpdir = TempDir::new("rustc").ok().expect("needs a temp dir");
+    let tmpdir = match TempDir::new("rustc") {
+        Ok(tmpdir) => tmpdir,
+        Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)),
+    };
+
     match crate_type {
         config::CrateTypeRlib => {
             link_rlib(sess, Some(trans), &objects, &out_filename,
@@ -568,7 +580,7 @@ fn link_binary_output(sess: &Session,
 fn object_filenames(sess: &Session, outputs: &OutputFilenames) -> Vec<PathBuf> {
     (0..sess.opts.cg.codegen_units).map(|i| {
         let ext = format!("{}.o", i);
-        outputs.temp_path(OutputTypeObject).with_extension(&ext)
+        outputs.temp_path(OutputType::Object).with_extension(&ext)
     }).collect()
 }
 
@@ -613,7 +625,7 @@ fn link_rlib<'a>(sess: &'a Session,
 
     for &(ref l, kind) in sess.cstore.get_used_libraries().borrow().iter() {
         match kind {
-            cstore::NativeStatic => ab.add_native_library(&l).unwrap(),
+            cstore::NativeStatic => ab.add_native_library(&l),
             cstore::NativeFramework | cstore::NativeUnknown => {}
         }
     }
@@ -715,7 +727,7 @@ fn link_rlib<'a>(sess: &'a Session,
                 // See the bottom of back::write::run_passes for an explanation
                 // of when we do and don't keep .0.bc files around.
                 let user_wants_numbered_bitcode =
-                        sess.opts.output_types.contains(&OutputTypeBitcode) &&
+                        sess.opts.output_types.contains_key(&OutputType::Bitcode) &&
                         sess.opts.cg.codegen_units > 1;
                 if !sess.opts.cg.save_temps && !user_wants_numbered_bitcode {
                     remove(sess, &bc_filename);
@@ -789,7 +801,7 @@ fn link_staticlib(sess: &Session, objects: &[PathBuf], out_filename: &Path,
         ab.build();
     }
     if !sess.target.target.options.no_compiler_rt {
-        ab.add_native_library("compiler-rt").unwrap();
+        ab.add_native_library("compiler-rt");
     }
 
     let mut all_native_libs = vec![];
@@ -873,6 +885,16 @@ fn link_natively(sess: &Session, dylib: bool,
     let prog = time(sess.time_passes(), "running linker", || cmd.output());
     match prog {
         Ok(prog) => {
+            fn escape_string(s: &[u8]) -> String {
+                str::from_utf8(s).map(|s| s.to_owned())
+                    .unwrap_or_else(|_| {
+                        let mut x = "Non-UTF-8 output: ".to_string();
+                        x.extend(s.iter()
+                                 .flat_map(|&b| ascii::escape_default(b))
+                                 .map(|b| char::from_u32(b as u32).unwrap()));
+                        x
+                    })
+            }
             if !prog.status.success() {
                 sess.err(&format!("linking with `{}` failed: {}",
                                  pname,
@@ -880,11 +902,11 @@ fn link_natively(sess: &Session, dylib: bool,
                 sess.note(&format!("{:?}", &cmd));
                 let mut output = prog.stderr.clone();
                 output.push_all(&prog.stdout);
-                sess.note(str::from_utf8(&output[..]).unwrap());
+                sess.note(&*escape_string(&output[..]));
                 sess.abort_if_errors();
             }
-            info!("linker stderr:\n{}", String::from_utf8(prog.stderr).unwrap());
-            info!("linker stdout:\n{}", String::from_utf8(prog.stdout).unwrap());
+            info!("linker stderr:\n{}", escape_string(&prog.stderr[..]));
+            info!("linker stdout:\n{}", escape_string(&prog.stdout[..]));
         },
         Err(e) => {
             sess.fatal(&format!("could not exec the linker `{}`: {}", pname, e));
@@ -967,7 +989,9 @@ fn link_args(cmd: &mut Linker,
     // default. Note that this does not happen for windows because windows pulls
     // in some large number of libraries and I couldn't quite figure out which
     // subset we wanted.
-    cmd.no_default_libraries();
+    if t.options.no_default_libraries {
+        cmd.no_default_libraries();
+    }
 
     // Take careful note of the ordering of the arguments we pass to the linker
     // here. Linkers will assume that things on the left depend on things to the
@@ -979,31 +1003,24 @@ fn link_args(cmd: &mut Linker,
     // such:
     //
     //  1. The local object that LLVM just generated
-    //  2. Upstream rust libraries
-    //  3. Local native libraries
+    //  2. Local native libraries
+    //  3. Upstream rust libraries
     //  4. Upstream native libraries
     //
-    // This is generally fairly natural, but some may expect 2 and 3 to be
-    // swapped. The reason that all native libraries are put last is that it's
-    // not recommended for a native library to depend on a symbol from a rust
-    // crate. If this is the case then a staticlib crate is recommended, solving
-    // the problem.
-    //
-    // Additionally, it is occasionally the case that upstream rust libraries
-    // depend on a local native library. In the case of libraries such as
-    // lua/glfw/etc the name of the library isn't the same across all platforms,
-    // so only the consumer crate of a library knows the actual name. This means
-    // that downstream crates will provide the #[link] attribute which upstream
-    // crates will depend on. Hence local native libraries are after out
-    // upstream rust crates.
+    // The rationale behind this ordering is that those items lower down in the
+    // list can't depend on items higher up in the list. For example nothing can
+    // depend on what we just generated (e.g. that'd be a circular dependency).
+    // Upstream rust libraries are not allowed to depend on our local native
+    // libraries as that would violate the structure of the DAG, in that
+    // scenario they are required to link to them as well in a shared fashion.
     //
-    // In theory this means that a symbol in an upstream native library will be
-    // shadowed by a local native library when it wouldn't have been before, but
-    // this kind of behavior is pretty platform specific and generally not
-    // recommended anyway, so I don't think we're shooting ourself in the foot
-    // much with that.
-    add_upstream_rust_crates(cmd, sess, dylib, tmpdir);
+    // Note that upstream rust libraries may contain native dependencies as
+    // well, but they also can't depend on what we just started to add to the
+    // link line. And finally upstream native libraries can't depend on anything
+    // in this DAG so far because they're only dylibs and dylibs can only depend
+    // on other dylibs (e.g. other native deps).
     add_local_native_libraries(cmd, sess);
+    add_upstream_rust_crates(cmd, sess, dylib, tmpdir);
     add_upstream_native_libraries(cmd, sess);
 
     // # Telling the linker what we're doing
index a4333dc10d6378a5f92bd9cce88bf939e4266e08..79a91e4f41650c19eb0d60da487f3f6f1b1bcca1 100644 (file)
@@ -19,7 +19,6 @@ use back::archive;
 use metadata::csearch;
 use middle::dependency_format::Linkage;
 use session::Session;
-use session::config::DebugInfoLevel::{NoDebugInfo, LimitedDebugInfo, FullDebugInfo};
 use session::config::CrateTypeDylib;
 use session::config;
 use syntax::ast;
@@ -159,12 +158,7 @@ impl<'a> Linker for GnuLinker<'a> {
     }
 
     fn no_default_libraries(&mut self) {
-        // Unfortunately right now passing -nodefaultlibs to gcc on windows
-        // doesn't work so hot (in terms of native dependencies). This if
-        // statement should hopefully be removed one day though!
-        if !self.sess.target.target.options.is_like_windows {
-            self.cmd.arg("-nodefaultlibs");
-        }
+        self.cmd.arg("-nodefaultlibs");
     }
 
     fn build_dylib(&mut self, out_filename: &Path) {
@@ -286,17 +280,9 @@ impl<'a> Linker for MsvcLinker<'a> {
     }
 
     fn debuginfo(&mut self) {
-        match self.sess.opts.debuginfo {
-            NoDebugInfo => {
-                // Do nothing if debuginfo is disabled
-            },
-            LimitedDebugInfo |
-            FullDebugInfo    => {
-                // This will cause the Microsoft linker to generate a PDB file
-                // from the CodeView line tables in the object files.
-                self.cmd.arg("/DEBUG");
-            }
-        }
+        // This will cause the Microsoft linker to generate a PDB file
+        // from the CodeView line tables in the object files.
+        self.cmd.arg("/DEBUG");
     }
 
     fn whole_archives(&mut self) {
index 00439c1fd5878ae46cb5829dc0929b24bbbeb406..ba6ec895a8e12e356d23f3094ad5e99a9cfb9ddc 100644 (file)
@@ -15,6 +15,7 @@ use llvm;
 use llvm::archive_ro::ArchiveRO;
 use llvm::{ModuleRef, TargetMachineRef, True, False};
 use rustc::util::common::time;
+use rustc::util::common::path2cstr;
 use back::write::{ModuleConfig, with_llvm_pmb};
 
 use libc;
@@ -24,7 +25,9 @@ use std::ffi::CString;
 
 pub fn run(sess: &session::Session, llmod: ModuleRef,
            tm: TargetMachineRef, reachable: &[String],
-           config: &ModuleConfig) {
+           config: &ModuleConfig,
+           name_extra: &str,
+           output_names: &config::OutputFilenames) {
     if sess.opts.cg.prefer_dynamic {
         sess.err("cannot prefer dynamic linking when performing LTO");
         sess.note("only 'staticlib' and 'bin' outputs are supported with LTO");
@@ -124,6 +127,14 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
         }
     }
 
+    if sess.opts.cg.save_temps {
+        let path = output_names.with_extension(&format!("{}.no-opt.lto.bc", name_extra));
+        let cstr = path2cstr(&path);
+        unsafe {
+            llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr());
+        }
+    }
+
     // Now we have one massive module inside of llmod. Time to run the
     // LTO-specific optimization passes that LLVM provides.
     //
index d75f2fcf126a941084612637d6237ba555b1d8f0..807a19c82838906f923fbd21efa2e3e6cc2d1894 100644 (file)
@@ -12,7 +12,7 @@ use back::lto;
 use back::link::{get_linker, remove};
 use session::config::{OutputFilenames, Passes, SomePasses, AllPasses};
 use session::Session;
-use session::config;
+use session::config::{self, OutputType};
 use llvm;
 use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef};
 use llvm::SMDiagnosticRef;
@@ -23,9 +23,10 @@ use syntax::codemap;
 use syntax::diagnostic;
 use syntax::diagnostic::{Emitter, Handler, Level};
 
+use std::collections::HashMap;
 use std::ffi::{CStr, CString};
 use std::fs;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 use std::ptr;
 use std::str;
 use std::sync::{Arc, Mutex};
@@ -33,15 +34,6 @@ use std::sync::mpsc::channel;
 use std::thread;
 use libc::{self, c_uint, c_int, c_void};
 
-#[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
-pub enum OutputType {
-    OutputTypeBitcode,
-    OutputTypeAssembly,
-    OutputTypeLlvmAssembly,
-    OutputTypeObject,
-    OutputTypeExe,
-}
-
 pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! {
     unsafe {
         let cstr = llvm::LLVMRustGetLastError();
@@ -333,6 +325,8 @@ struct CodegenContext<'a> {
     plugin_passes: Vec<String>,
     // LLVM optimizations for which we want to print remarks.
     remark: Passes,
+    // Worker thread number
+    worker: usize,
 }
 
 impl<'a> CodegenContext<'a> {
@@ -342,6 +336,7 @@ impl<'a> CodegenContext<'a> {
             handler: sess.diagnostic().handler(),
             plugin_passes: sess.plugin_llvm_passes.borrow().clone(),
             remark: sess.opts.cg.remark.clone(),
+            worker: 0,
         }
     }
 }
@@ -484,9 +479,9 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
         cgcx.handler.abort_if_errors();
 
         // Finally, run the actual optimization passes
-        time(config.time_passes, "llvm function passes", ||
+        time(config.time_passes, &format!("llvm function passes [{}]", cgcx.worker), ||
              llvm::LLVMRustRunFunctionPassManager(fpm, llmod));
-        time(config.time_passes, "llvm module passes", ||
+        time(config.time_passes, &format!("llvm module passes [{}]", cgcx.worker), ||
              llvm::LLVMRunPassManager(mpm, llmod));
 
         // Deallocate managers that we're now done with
@@ -496,7 +491,8 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
         match cgcx.lto_ctxt {
             Some((sess, reachable)) if sess.lto() =>  {
                 time(sess.time_passes(), "all lto passes", ||
-                     lto::run(sess, llmod, tm, reachable, &config));
+                     lto::run(sess, llmod, tm, reachable, &config,
+                              &name_extra, &output_names));
 
                 if config.emit_lto_bc {
                     let name = format!("{}.lto.bc", name_extra);
@@ -536,7 +532,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
         llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
     }
 
-    time(config.time_passes, "codegen passes", || {
+    time(config.time_passes, &format!("codegen passes [{}]", cgcx.worker), || {
         if config.emit_ir {
             let ext = format!("{}.ll", name_extra);
             let out = output_names.with_extension(&ext);
@@ -570,7 +566,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
 
 pub fn run_passes(sess: &Session,
                   trans: &CrateTranslation,
-                  output_types: &[config::OutputType],
+                  output_types: &HashMap<OutputType, Option<PathBuf>>,
                   crate_output: &OutputFilenames) {
     // It's possible that we have `codegen_units > 1` but only one item in
     // `trans.modules`.  We could theoretically proceed and do LTO in that
@@ -610,32 +606,32 @@ pub fn run_passes(sess: &Session,
     // archive in order to allow LTO against it.
     let needs_crate_bitcode =
             sess.crate_types.borrow().contains(&config::CrateTypeRlib) &&
-            sess.opts.output_types.contains(&config::OutputTypeExe);
+            sess.opts.output_types.contains_key(&OutputType::Exe);
     let needs_crate_object =
-            sess.opts.output_types.contains(&config::OutputTypeExe);
+            sess.opts.output_types.contains_key(&OutputType::Exe);
     if needs_crate_bitcode {
         modules_config.emit_bc = true;
     }
 
-    for output_type in output_types {
+    for output_type in output_types.keys() {
         match *output_type {
-            config::OutputTypeBitcode => { modules_config.emit_bc = true; },
-            config::OutputTypeLlvmAssembly => { modules_config.emit_ir = true; },
-            config::OutputTypeAssembly => {
+            OutputType::Bitcode => { modules_config.emit_bc = true; },
+            OutputType::LlvmAssembly => { modules_config.emit_ir = true; },
+            OutputType::Assembly => {
                 modules_config.emit_asm = true;
                 // If we're not using the LLVM assembler, this function
                 // could be invoked specially with output_type_assembly, so
                 // in this case we still want the metadata object file.
-                if !sess.opts.output_types.contains(&config::OutputTypeAssembly) {
+                if !sess.opts.output_types.contains_key(&OutputType::Assembly) {
                     metadata_config.emit_obj = true;
                 }
             },
-            config::OutputTypeObject => { modules_config.emit_obj = true; },
-            config::OutputTypeExe => {
+            OutputType::Object => { modules_config.emit_obj = true; },
+            OutputType::Exe => {
                 modules_config.emit_obj = true;
                 metadata_config.emit_obj = true;
             },
-            config::OutputTypeDepInfo => {}
+            OutputType::DepInfo => {}
         }
     }
 
@@ -685,8 +681,9 @@ pub fn run_passes(sess: &Session,
         }
     };
 
-    let copy_if_one_unit = |ext: &str, output_type: config::OutputType, keep_numbered: bool| {
-        // Three cases:
+    let copy_if_one_unit = |ext: &str,
+                            output_type: OutputType,
+                            keep_numbered: bool| {
         if sess.opts.cg.codegen_units == 1 {
             // 1) Only one codegen unit.  In this case it's no difficulty
             //    to copy `foo.0.x` to `foo.x`.
@@ -696,17 +693,20 @@ pub fn run_passes(sess: &Session,
                 // The user just wants `foo.x`, not `foo.0.x`.
                 remove(sess, &crate_output.with_extension(ext));
             }
+        } else if crate_output.outputs.contains_key(&output_type) {
+            // 2) Multiple codegen units, with `--emit foo=some_name`.  We have
+            //    no good solution for this case, so warn the user.
+            sess.warn(&format!("ignoring emit path because multiple .{} files \
+                                were produced", ext));
+        } else if crate_output.single_output_file.is_some() {
+            // 3) Multiple codegen units, with `-o some_name`.  We have
+            //    no good solution for this case, so warn the user.
+            sess.warn(&format!("ignoring -o because multiple .{} files \
+                                were produced", ext));
         } else {
-            if crate_output.single_output_file.is_some() {
-                // 2) Multiple codegen units, with `-o some_name`.  We have
-                //    no good solution for this case, so warn the user.
-                sess.warn(&format!("ignoring -o because multiple .{} files were produced",
-                                  ext));
-            } else {
-                // 3) Multiple codegen units, but no `-o some_name`.  We
-                //    just leave the `foo.0.x` files in place.
-                // (We don't have to do any work in this case.)
-            }
+            // 4) Multiple codegen units, but no explicit name.  We
+            //    just leave the `foo.0.x` files in place.
+            // (We don't have to do any work in this case.)
         }
     };
 
@@ -715,27 +715,27 @@ pub fn run_passes(sess: &Session,
     // to get rid of it.
     let mut user_wants_bitcode = false;
     let mut user_wants_objects = false;
-    for output_type in output_types {
+    for output_type in output_types.keys() {
         match *output_type {
-            config::OutputTypeBitcode => {
+            OutputType::Bitcode => {
                 user_wants_bitcode = true;
                 // Copy to .bc, but always keep the .0.bc.  There is a later
                 // check to figure out if we should delete .0.bc files, or keep
                 // them for making an rlib.
-                copy_if_one_unit("0.bc", config::OutputTypeBitcode, true);
+                copy_if_one_unit("0.bc", OutputType::Bitcode, true);
             }
-            config::OutputTypeLlvmAssembly => {
-                copy_if_one_unit("0.ll", config::OutputTypeLlvmAssembly, false);
+            OutputType::LlvmAssembly => {
+                copy_if_one_unit("0.ll", OutputType::LlvmAssembly, false);
             }
-            config::OutputTypeAssembly => {
-                copy_if_one_unit("0.s", config::OutputTypeAssembly, false);
+            OutputType::Assembly => {
+                copy_if_one_unit("0.s", OutputType::Assembly, false);
             }
-            config::OutputTypeObject => {
+            OutputType::Object => {
                 user_wants_objects = true;
-                copy_if_one_unit("0.o", config::OutputTypeObject, true);
+                copy_if_one_unit("0.o", OutputType::Object, true);
             }
-            config::OutputTypeExe |
-            config::OutputTypeDepInfo => {}
+            OutputType::Exe |
+            OutputType::DepInfo => {}
         }
     }
     let user_wants_bitcode = user_wants_bitcode;
@@ -872,6 +872,7 @@ fn run_work_multithreaded(sess: &Session,
                 handler: &diag_handler,
                 plugin_passes: plugin_passes,
                 remark: remark,
+                worker: i,
             };
 
             loop {
@@ -912,8 +913,8 @@ fn run_work_multithreaded(sess: &Session,
 pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
     let (pname, mut cmd) = get_linker(sess);
 
-    cmd.arg("-c").arg("-o").arg(&outputs.path(config::OutputTypeObject))
-                           .arg(&outputs.temp_path(config::OutputTypeAssembly));
+    cmd.arg("-c").arg("-o").arg(&outputs.path(OutputType::Object))
+                           .arg(&outputs.temp_path(OutputType::Assembly));
     debug!("{:?}", cmd);
 
     match cmd.output() {
diff --git a/src/librustc_trans/diagnostics.rs b/src/librustc_trans/diagnostics.rs
new file mode 100644 (file)
index 0000000..2ad2e75
--- /dev/null
@@ -0,0 +1,122 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(non_snake_case)]
+
+register_long_diagnostics! {
+
+E0510: r##"
+`return_address` was used in an invalid context. Erroneous code example:
+
+```
+extern "rust-intrinsic" {
+    fn return_address() -> *const u8;
+}
+
+pub unsafe fn by_value() -> i32 {
+    let _ = return_address();
+    // error: invalid use of `return_address` intrinsic: function does
+    //        not use out pointer
+    0
+}
+```
+
+Return values may be stored in a return register(s) or written into a so-called
+out pointer. In case the returned value is too big (this is
+target-ABI-dependent and generally not portable or future proof) to fit into
+the return register(s), the compiler will return the value by writing it into
+space allocated in the caller's stack frame. Example:
+
+```
+extern "rust-intrinsic" {
+    fn return_address() -> *const u8;
+}
+
+pub unsafe fn by_pointer() -> String {
+    let _ = return_address();
+    String::new() // ok!
+}
+```
+"##,
+
+E0511: r##"
+Invalid monomorphization of an intrinsic function was used. Erroneous code
+example:
+
+```
+extern "platform-intrinsic" {
+    fn simd_add<T>(a: T, b: T) -> T;
+}
+
+unsafe { simd_add(0, 1); }
+// error: invalid monomorphization of `simd_add` intrinsic
+```
+
+The generic type has to be a SIMD type. Example:
+
+```
+#[repr(simd)]
+#[derive(Copy, Clone)]
+struct i32x1(i32);
+
+extern "platform-intrinsic" {
+    fn simd_add<T>(a: T, b: T) -> T;
+}
+
+unsafe { simd_add(i32x1(0), i32x1(1)); } // ok!
+```
+"##,
+
+E0512: r##"
+Transmute with two differently sized types was attempted. Erroneous code
+example:
+
+```
+extern "rust-intrinsic" {
+    pub fn ctpop8(x: u8) -> u8;
+}
+
+fn main() {
+    unsafe { ctpop8(::std::mem::transmute(0u16)); }
+    // error: transmute called with differently sized types
+}
+```
+
+Please use types with same size or use the expected type directly. Example:
+
+```
+extern "rust-intrinsic" {
+    pub fn ctpop8(x: u8) -> u8;
+}
+
+fn main() {
+    unsafe { ctpop8(::std::mem::transmute(0i8)); } // ok!
+    // or:
+    unsafe { ctpop8(0u8); } // ok!
+}
+```
+"##,
+
+E0515: r##"
+A constant index expression was out of bounds. Erroneous code example:
+
+```
+let x = &[0, 1, 2][7]; // error: const index-expr is out of bounds
+```
+
+Please specify a valid index (not inferior to 0 or superior to array length).
+Example:
+
+```
+let x = &[0, 1, 2][2]; // ok
+```
+"##,
+
+}
index a7fb3af138453ffa024b9b5eb2ad05d20425e340..e02ce49132a7c10e3983d4d9996efdce37473374 100644 (file)
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(const_fn)]
+#![feature(custom_attribute)]
+#![allow(unused_attributes)]
 #![feature(iter_cmp)]
 #![feature(iter_arith)]
 #![feature(libc)]
-#![feature(path_ext)]
-#![feature(path_ext)]
-#![feature(path_relative_from)]
 #![feature(path_relative_from)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #![feature(unicode)]
-#![feature(unicode)]
 #![feature(vec_push_all)]
 
 #![allow(trivial_casts)]
@@ -80,6 +78,8 @@ pub mod back {
     pub mod msvc;
 }
 
+pub mod diagnostics;
+
 pub mod trans;
 pub mod save;
 
index 62b2f2949fab669f28fae64cd16b120d73bf6855..f6f504e27aefcdf22c8c8bc4678440c61485a601 100644 (file)
@@ -47,7 +47,7 @@ use syntax::visit::{self, Visitor};
 use syntax::print::pprust::{path_to_string, ty_to_string};
 use syntax::ptr::P;
 
-use rustc_front::lowering::lower_expr;
+use rustc_front::lowering::{lower_expr, LoweringContext};
 
 use super::span_utils::SpanUtils;
 use super::recorder::{Recorder, FmtStrs};
@@ -58,7 +58,7 @@ macro_rules! down_cast_data {
             data
         } else {
             $this.sess.span_bug($sp, &format!("unexpected data kind: {:?}", $id));
-        };
+        }
     };
 }
 
@@ -66,28 +66,33 @@ pub struct DumpCsvVisitor<'l, 'tcx: 'l> {
     save_ctxt: SaveContext<'l, 'tcx>,
     sess: &'l Session,
     tcx: &'l ty::ctxt<'tcx>,
-    analysis: &'l ty::CrateAnalysis,
+    analysis: &'l ty::CrateAnalysis<'l>,
 
     span: SpanUtils<'l>,
-    fmt: FmtStrs<'l>,
+    fmt: FmtStrs<'l, 'tcx>,
 
     cur_scope: NodeId,
 }
 
 impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
     pub fn new(tcx: &'l ty::ctxt<'tcx>,
-               analysis: &'l ty::CrateAnalysis,
+               lcx: &'l LoweringContext<'l>,
+               analysis: &'l ty::CrateAnalysis<'l>,
                output_file: Box<File>)
                -> DumpCsvVisitor<'l, 'tcx> {
         let span_utils = SpanUtils::new(&tcx.sess);
         DumpCsvVisitor {
             sess: &tcx.sess,
             tcx: tcx,
-            save_ctxt: SaveContext::from_span_utils(tcx, span_utils.clone()),
+            save_ctxt: SaveContext::from_span_utils(tcx, lcx, span_utils.clone()),
             analysis: analysis,
             span: span_utils.clone(),
-            fmt: FmtStrs::new(box Recorder { out: output_file, dump_spans: false },
-                              span_utils),
+            fmt: FmtStrs::new(box Recorder {
+                                  out: output_file,
+                                  dump_spans: false,
+                              },
+                              span_utils,
+                              tcx),
             cur_scope: 0,
         }
     }
@@ -123,13 +128,16 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
         // always using the first ones. So, only error out if we don't have enough spans.
         // What could go wrong...?
         if spans.len() < path.segments.len() {
-            error!("Mis-calculated spans for path '{}'. \
-                    Found {} spans, expected {}. Found spans:",
-                   path_to_string(path), spans.len(), path.segments.len());
+            error!("Mis-calculated spans for path '{}'. Found {} spans, expected {}. Found spans:",
+                   path_to_string(path),
+                   spans.len(),
+                   path.segments.len());
             for s in &spans {
                 let loc = self.sess.codemap().lookup_char_pos(s.lo);
                 error!("    '{}' in {}, line {}",
-                       self.span.snippet(*s), loc.file.name, loc.line);
+                       self.span.snippet(*s),
+                       loc.file.name,
+                       loc.line);
             }
             return vec!();
         }
@@ -168,10 +176,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             } else {
                 qualname.clone()
             };
-            self.fmt.sub_mod_ref_str(path.span,
-                                     *span,
-                                     &qualname,
-                                     self.cur_scope);
+            self.fmt.sub_mod_ref_str(path.span, *span, &qualname, self.cur_scope);
         }
     }
 
@@ -191,10 +196,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             } else {
                 qualname.clone()
             };
-            self.fmt.sub_mod_ref_str(path.span,
-                                     *span,
-                                     &qualname,
-                                     self.cur_scope);
+            self.fmt.sub_mod_ref_str(path.span, *span, &qualname, self.cur_scope);
         }
     }
 
@@ -210,9 +212,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
 
         // write the trait part of the sub-path
         let (ref span, ref qualname) = sub_paths[len-2];
-        self.fmt.sub_type_ref_str(path.span,
-                                  *span,
-                                  &qualname);
+        self.fmt.sub_type_ref_str(path.span, *span, &qualname);
 
         // write the other sub-paths
         if len <= 2 {
@@ -220,10 +220,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
         }
         let sub_paths = &sub_paths[..len-2];
         for &(ref span, ref qualname) in sub_paths {
-            self.fmt.sub_mod_ref_str(path.span,
-                                     *span,
-                                     &qualname,
-                                     self.cur_scope);
+            self.fmt.sub_mod_ref_str(path.span, *span, &qualname, self.cur_scope);
         }
     }
 
@@ -231,11 +228,12 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
     fn lookup_type_ref(&self, ref_id: NodeId) -> Option<DefId> {
         if !self.tcx.def_map.borrow().contains_key(&ref_id) {
             self.sess.bug(&format!("def_map has no key for {} in lookup_type_ref",
-                                  ref_id));
+                                   ref_id));
         }
         let def = self.tcx.def_map.borrow().get(&ref_id).unwrap().full_def();
         match def {
-            def::DefPrimTy(_) => None,
+            def::DefPrimTy(..) => None,
+            def::DefSelfTy(..) => None,
             _ => Some(def.def_id()),
         }
     }
@@ -243,8 +241,9 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
     fn lookup_def_kind(&self, ref_id: NodeId, span: Span) -> Option<recorder::Row> {
         let def_map = self.tcx.def_map.borrow();
         if !def_map.contains_key(&ref_id) {
-            self.sess.span_bug(span, &format!("def_map has no key for {} in lookup_def_kind",
-                                             ref_id));
+            self.sess.span_bug(span,
+                               &format!("def_map has no key for {} in lookup_def_kind",
+                                        ref_id));
         }
         let def = def_map.get(&ref_id).unwrap().full_def();
         match def {
@@ -257,21 +256,20 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             def::DefStatic(_, _) |
             def::DefConst(_) |
             def::DefAssociatedConst(..) |
-            def::DefLocal(_) |
+            def::DefLocal(..) |
             def::DefVariant(_, _, _) |
             def::DefUpvar(..) => Some(recorder::VarRef),
 
             def::DefFn(..) => Some(recorder::FnRef),
 
             def::DefSelfTy(..) |
-            def::DefRegion(_) |
             def::DefLabel(_) |
             def::DefTyParam(..) |
             def::DefUse(_) |
             def::DefMethod(..) |
             def::DefPrimTy(_) => {
-                self.sess.span_bug(span, &format!("lookup_def_kind for unexpected item: {:?}",
-                                                 def));
+                self.sess.span_bug(span,
+                                   &format!("lookup_def_kind for unexpected item: {:?}", def));
             }
         }
     }
@@ -340,10 +338,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             self.nest(id, |v| v.visit_block(body));
         }
 
-        self.process_generic_params(&sig.generics,
-                                    span,
-                                    &method_data.qualname,
-                                    id);
+        self.process_generic_params(&sig.generics, span, &method_data.qualname, id);
     }
 
     fn process_trait_ref(&mut self, trait_ref: &ast::TraitRef) {
@@ -382,18 +377,14 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
         // However full span is the entire enum/fn/struct block, so we only want
         // the first few to match the number of generics we're looking for.
         let param_sub_spans = self.span.spans_for_ty_params(full_span,
-                                                           (generics.ty_params.len() as isize));
+                                                            (generics.ty_params.len() as isize));
         for (param, param_ss) in generics.ty_params.iter().zip(param_sub_spans) {
             // Append $id to name to make sure each one is unique
             let name = format!("{}::{}${}",
                                prefix,
                                escape(self.span.snippet(param_ss)),
                                id);
-            self.fmt.typedef_str(full_span,
-                                 Some(param_ss),
-                                 param.id,
-                                 &name,
-                                 "");
+            self.fmt.typedef_str(full_span, Some(param_ss), param.id, &name, "");
         }
         self.visit_generics(generics);
     }
@@ -444,19 +435,18 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
 
     fn process_const(&mut self,
                      id: ast::NodeId,
-                     ident: &ast::Ident,
+                     name: ast::Name,
                      span: Span,
                      typ: &ast::Ty,
                      expr: &ast::Expr) {
         let qualname = format!("::{}", self.tcx.map.path_to_string(id));
 
-        let sub_span = self.span.sub_span_after_keyword(span,
-                                                        keywords::Const);
+        let sub_span = self.span.sub_span_after_keyword(span, keywords::Const);
 
         self.fmt.static_str(span,
                             sub_span,
                             id,
-                            &ident.name.as_str(),
+                            &name.as_str(),
                             &qualname,
                             &self.span.snippet(expr.span),
                             &ty_to_string(&*typ),
@@ -469,26 +459,22 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
 
     fn process_struct(&mut self,
                       item: &ast::Item,
-                      def: &ast::StructDef,
+                      def: &ast::VariantData,
                       ty_params: &ast::Generics) {
         let qualname = format!("::{}", self.tcx.map.path_to_string(item.id));
 
-        let ctor_id = match def.ctor_id {
-            Some(node_id) => node_id,
-            None => ast::DUMMY_NODE_ID,
-        };
         let val = self.span.snippet(item.span);
         let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Struct);
         self.fmt.struct_str(item.span,
                             sub_span,
                             item.id,
-                            ctor_id,
+                            def.id(),
                             &qualname,
                             self.cur_scope,
                             &val);
 
         // fields
-        for field in &def.fields {
+        for field in def.fields() {
             self.process_struct_field_def(field, item.id);
             self.visit_ty(&field.node.ty);
         }
@@ -515,40 +501,19 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             qualname.push_str("::");
             qualname.push_str(name);
             let val = self.span.snippet(variant.span);
-            match variant.node.kind {
-                ast::TupleVariantKind(ref args) => {
-                    // first ident in span is the variant's name
-                    self.fmt.tuple_variant_str(variant.span,
-                                               self.span.span_for_first_ident(variant.span),
-                                               variant.node.id,
-                                               name,
-                                               &qualname,
-                                               &enum_data.qualname,
-                                               &val,
-                                               enum_data.id);
-                    for arg in args {
-                        self.visit_ty(&*arg.ty);
-                    }
-                }
-                ast::StructVariantKind(ref struct_def) => {
-                    let ctor_id = match struct_def.ctor_id {
-                        Some(node_id) => node_id,
-                        None => ast::DUMMY_NODE_ID,
-                    };
-                    self.fmt.struct_variant_str(variant.span,
-                                                self.span.span_for_first_ident(variant.span),
-                                                variant.node.id,
-                                                ctor_id,
-                                                &qualname,
-                                                &enum_data.qualname,
-                                                &val,
-                                                enum_data.id);
-
-                    for field in &struct_def.fields {
-                        self.process_struct_field_def(field, variant.node.id);
-                        self.visit_ty(&*field.node.ty);
-                    }
-                }
+
+            self.fmt.struct_variant_str(variant.span,
+                                        self.span.span_for_first_ident(variant.span),
+                                        variant.node.data.id(),
+                                        variant.node.data.id(),
+                                        &qualname,
+                                        &enum_data.qualname,
+                                        &val,
+                                        enum_data.id);
+
+            for field in variant.node.data.fields() {
+                self.process_struct_field_def(field, variant.node.data.id());
+                self.visit_ty(&*field.node.ty);
             }
         }
         self.process_generic_params(ty_params, item.span, &enum_data.qualname, enum_data.id);
@@ -631,10 +596,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                                      sub_span,
                                      id,
                                      self.cur_scope);
-                    self.fmt.inherit_str(trait_ref.path.span,
-                                         sub_span,
-                                         id,
-                                         item.id);
+                    self.fmt.inherit_str(trait_ref.path.span, sub_span, id, item.id);
                 }
                 None => (),
             }
@@ -669,18 +631,18 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             Some(pd) => pd,
             None => {
                 self.tcx.sess.span_bug(path.span,
-                                       &format!("Unexpected def kind while looking \
-                                                 up path in `{}`",
+                                       &format!("Unexpected def kind while looking up path in \
+                                                 `{}`",
                                                 self.span.snippet(path.span)))
             }
         };
         match path_data {
             Data::VariableRefData(ref vrd) => {
                 self.fmt.ref_str(ref_kind.unwrap_or(recorder::VarRef),
-                                                    path.span,
-                                                    Some(vrd.span),
-                                                    vrd.ref_id,
-                                                    vrd.scope);
+                                 path.span,
+                                 Some(vrd.span),
+                                 vrd.ref_id,
+                                 vrd.scope);
 
             }
             Data::TypeRefData(ref trd) => {
@@ -698,10 +660,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                                        mcd.scope);
             }
             Data::FunctionCallData(fcd) => {
-                self.fmt.fn_call_str(path.span,
-                                     Some(fcd.span),
-                                     fcd.ref_id,
-                                     fcd.scope);
+                self.fmt.fn_call_str(path.span, Some(fcd.span), fcd.ref_id, fcd.scope);
             }
             _ => {
                 self.sess.span_bug(path.span,
@@ -721,7 +680,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                     }
                 }
             }
-            def::DefLocal(_) |
+            def::DefLocal(..) |
             def::DefStatic(_,_) |
             def::DefConst(..) |
             def::DefAssociatedConst(..) |
@@ -758,9 +717,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                     continue;
                 }
 
-                let field_data = self.save_ctxt.get_field_ref_data(field,
-                                                                   variant,
-                                                                   scope);
+                let field_data = self.save_ctxt.get_field_ref_data(field, variant, scope);
                 self.fmt.ref_str(recorder::VarRef,
                                  field.ident.span,
                                  Some(field_data.span),
@@ -771,7 +728,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             }
         }
 
-        visit::walk_expr_opt(self, base)
+        walk_list!(self, visit_expr, base);
     }
 
     fn process_method_call(&mut self, ex: &ast::Expr, args: &Vec<P<ast::Expr>>) {
@@ -785,7 +742,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
         }
 
         // walk receiver and args
-        visit::walk_exprs(self, &args);
+        walk_list!(self, visit_expr, args);
     }
 
     fn process_pat(&mut self, p: &ast::Pat) {
@@ -807,11 +764,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
 
                     let sub_span = self.span.span_for_first_ident(span);
                     if let Some(f) = variant.find_field_named(field.ident.name) {
-                        self.fmt.ref_str(recorder::VarRef,
-                                         span,
-                                         sub_span,
-                                         f.did,
-                                         self.cur_scope);
+                        self.fmt.ref_str(recorder::VarRef, span, sub_span, f.did, self.cur_scope);
                     }
                     self.visit_pat(&field.pat);
                 }
@@ -819,6 +772,35 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             _ => visit::walk_pat(self, p),
         }
     }
+
+
+    fn process_var_decl(&mut self, p: &ast::Pat, value: String) {
+        // The local could declare multiple new vars, we must walk the
+        // pattern and collect them all.
+        let mut collector = PathCollector::new();
+        collector.visit_pat(&p);
+        self.visit_pat(&p);
+
+        for &(id, ref p, immut, _) in &collector.collected_paths {
+            let value = if immut == ast::MutImmutable {
+                value.to_string()
+            } else {
+                "<mutable>".to_string()
+            };
+            let types = self.tcx.node_types();
+            let typ = types.get(&id).unwrap().to_string();
+            // Get the span only for the name of the variable (I hope the path
+            // is only ever a variable name, but who knows?).
+            let sub_span = self.span.span_for_last_ident(p.span);
+            // Rust uses the id of the pattern for var lookups, so we'll use it too.
+            self.fmt.variable_str(p.span,
+                                  sub_span,
+                                  id,
+                                  &path_to_string(p),
+                                  &value,
+                                  &typ);
+        }
+    }
 }
 
 impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
@@ -849,11 +831,11 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
 
                         // 'use' always introduces an alias, if there is not an explicit
                         // one, there is an implicit one.
-                        let sub_span =
-                            match self.span.sub_span_after_keyword(use_item.span, keywords::As) {
-                                Some(sub_span) => Some(sub_span),
-                                None => sub_span,
-                            };
+                        let sub_span = match self.span.sub_span_after_keyword(use_item.span,
+                                                                              keywords::As) {
+                            Some(sub_span) => Some(sub_span),
+                            None => sub_span,
+                        };
 
                         self.fmt.use_alias_str(path.span,
                                                sub_span,
@@ -877,8 +859,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
                             }
                         }
 
-                        let sub_span = self.span.sub_span_of_token(path.span,
-                                                                   token::BinOp(token::Star));
+                        let sub_span = self.span
+                                           .sub_span_of_token(path.span, token::BinOp(token::Star));
                         self.fmt.use_glob_str(path.span,
                                               sub_span,
                                               item.id,
@@ -893,10 +875,11 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
                                     match self.lookup_type_ref(id) {
                                         Some(def_id) => match self.lookup_def_kind(id, plid.span) {
                                             Some(kind) => {
-                                                self.fmt.ref_str(
-                                                        kind, plid.span,
-                                                        Some(plid.span),
-                                                        def_id, self.cur_scope);
+                                                self.fmt.ref_str(kind,
+                                                                 plid.span,
+                                                                 Some(plid.span),
+                                                                 def_id,
+                                                                 self.cur_scope);
                                             }
                                             None => (),
                                         },
@@ -935,18 +918,14 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
                 self.process_static_or_const_item(item, typ, expr),
             ast::ItemConst(ref typ, ref expr) =>
                 self.process_static_or_const_item(item, &typ, &expr),
-            ast::ItemStruct(ref def, ref ty_params) => self.process_struct(item, &**def, ty_params),
+            ast::ItemStruct(ref def, ref ty_params) => self.process_struct(item, def, ty_params),
             ast::ItemEnum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
             ast::ItemImpl(_, _,
                           ref ty_params,
                           ref trait_ref,
                           ref typ,
                           ref impl_items) => {
-                self.process_impl(item,
-                                  ty_params,
-                                  trait_ref,
-                                  &typ,
-                                  impl_items)
+                self.process_impl(item, ty_params, trait_ref, &typ, impl_items)
             }
             ast::ItemTrait(_, ref generics, ref trait_refs, ref methods) =>
                 self.process_trait(item, generics, trait_refs, methods),
@@ -958,11 +937,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
                 let qualname = format!("::{}", self.tcx.map.path_to_string(item.id));
                 let value = ty_to_string(&**ty);
                 let sub_span = self.span.sub_span_after_keyword(item.span, keywords::Type);
-                self.fmt.typedef_str(item.span,
-                                     sub_span,
-                                     item.id,
-                                     &qualname,
-                                     &value);
+                self.fmt.typedef_str(item.span, sub_span, item.id, &qualname, &value);
 
                 self.visit_ty(&**ty);
                 self.process_generic_params(ty_params, item.span, &qualname, item.id);
@@ -988,8 +963,11 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
     fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
         match trait_item.node {
             ast::ConstTraitItem(ref ty, Some(ref expr)) => {
-                self.process_const(trait_item.id, &trait_item.ident,
-                                   trait_item.span, &*ty, &*expr);
+                self.process_const(trait_item.id,
+                                   trait_item.ident.name,
+                                   trait_item.span,
+                                   &*ty,
+                                   &*expr);
             }
             ast::MethodTraitItem(ref sig, ref body) => {
                 self.process_method(sig,
@@ -1006,8 +984,11 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
     fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) {
         match impl_item.node {
             ast::ConstImplItem(ref ty, ref expr) => {
-                self.process_const(impl_item.id, &impl_item.ident,
-                                   impl_item.span, &ty, &expr);
+                self.process_const(impl_item.id,
+                                   impl_item.ident.name,
+                                   impl_item.span,
+                                   &ty,
+                                   &expr);
             }
             ast::MethodImplItem(ref sig, ref body) => {
                 self.process_method(sig,
@@ -1031,11 +1012,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
                 match self.lookup_type_ref(t.id) {
                     Some(id) => {
                         let sub_span = self.span.sub_span_for_type_name(t.span);
-                        self.fmt.ref_str(recorder::TypeRef,
-                                         t.span,
-                                         sub_span,
-                                         id,
-                                         self.cur_scope);
+                        self.fmt.ref_str(recorder::TypeRef, t.span, sub_span, id, self.cur_scope);
                     }
                     None => (),
                 }
@@ -1064,14 +1041,10 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
                 visit::walk_expr(self, ex);
             }
             ast::ExprStruct(ref path, ref fields, ref base) => {
-                let hir_expr = lower_expr(ex);
+                let hir_expr = lower_expr(self.save_ctxt.lcx, ex);
                 let adt = self.tcx.expr_ty(&hir_expr).ty_adt_def().unwrap();
                 let def = self.tcx.resolve_expr(&hir_expr);
-                self.process_struct_lit(ex,
-                                        path,
-                                        fields,
-                                        adt.variant_of_def(def),
-                                        base)
+                self.process_struct_lit(ex, path, fields, adt.variant_of_def(def), base)
             }
             ast::ExprMethodCall(_, _, ref args) => self.process_method_call(ex, args),
             ast::ExprField(ref sub_ex, _) => {
@@ -1097,7 +1070,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
 
                 self.visit_expr(&**sub_ex);
 
-                let hir_node = self.tcx.map.expect_expr(sub_ex.id);
+                let hir_node = lower_expr(self.save_ctxt.lcx, sub_ex);
                 let ty = &self.tcx.expr_ty_adjusted(&hir_node).sty;
                 match *ty {
                     ty::TyStruct(def, _) => {
@@ -1110,8 +1083,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
                     }
                     ty::TyTuple(_) => {}
                     _ => self.sess.span_bug(ex.span,
-                                            &format!("Expected struct or tuple \
-                                                      type, found {:?}", ty)),
+                                            &format!("Expected struct or tuple type, found {:?}",
+                                                     ty)),
                 }
             }
             ast::ExprClosure(_, ref decl, ref body) => {
@@ -1135,6 +1108,20 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
                 // walk the body
                 self.nest(ex.id, |v| v.visit_block(&**body));
             }
+            ast::ExprForLoop(ref pattern, ref subexpression, ref block, _) |
+            ast::ExprWhileLet(ref pattern, ref subexpression, ref block, _) => {
+                let value = self.span.snippet(mk_sp(ex.span.lo, subexpression.span.hi));
+                self.process_var_decl(pattern, value);
+                visit::walk_expr(self, subexpression);
+                visit::walk_block(self, block);
+            }
+            ast::ExprIfLet(ref pattern, ref subexpression, ref block, ref opt_else) => {
+                let value = self.span.snippet(mk_sp(ex.span.lo, subexpression.span.hi));
+                self.process_var_decl(pattern, value);
+                visit::walk_expr(self, subexpression);
+                visit::walk_block(self, block);
+                opt_else.as_ref().map(|el| visit::walk_expr(self, el));
+            }
             _ => {
                 visit::walk_expr(self, ex)
             }
@@ -1165,25 +1152,20 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
             let def_map = self.tcx.def_map.borrow();
             if !def_map.contains_key(&id) {
                 self.sess.span_bug(p.span,
-                                   &format!("def_map has no key for {} in visit_arm",
-                                           id));
+                                   &format!("def_map has no key for {} in visit_arm", id));
             }
             let def = def_map.get(&id).unwrap().full_def();
             match def {
-                def::DefLocal(id) => {
+                def::DefLocal(_, id) => {
                     let value = if immut == ast::MutImmutable {
                         self.span.snippet(p.span).to_string()
                     } else {
                         "<mutable>".to_string()
                     };
 
-                    assert!(p.segments.len() == 1, "qualified path for local variable def in arm");
-                    self.fmt.variable_str(p.span,
-                                          Some(p.span),
-                                          id,
-                                          &path_to_string(p),
-                                          &value,
-                                          "")
+                    assert!(p.segments.len() == 1,
+                            "qualified path for local variable def in arm");
+                    self.fmt.variable_str(p.span, Some(p.span), id, &path_to_string(p), &value, "")
                 }
                 def::DefVariant(..) | def::DefTy(..) | def::DefStruct(..) => {
                     paths_to_process.push((id, p.clone(), Some(ref_kind)))
@@ -1200,7 +1182,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
         for &(id, ref path, ref_kind) in &paths_to_process {
             self.process_path(id, path, ref_kind);
         }
-        visit::walk_expr_opt(self, &arm.guard);
+        walk_list!(self, visit_expr, &arm.guard);
         self.visit_expr(&arm.body);
     }
 
@@ -1217,36 +1199,12 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
             return
         }
 
-        // The local could declare multiple new vars, we must walk the
-        // pattern and collect them all.
-        let mut collector = PathCollector::new();
-        collector.visit_pat(&l.pat);
-        self.visit_pat(&l.pat);
-
         let value = self.span.snippet(l.span);
-
-        for &(id, ref p, immut, _) in &collector.collected_paths {
-            let value = if immut == ast::MutImmutable {
-                value.to_string()
-            } else {
-                "<mutable>".to_string()
-            };
-            let types = self.tcx.node_types();
-            let typ = types.get(&id).unwrap().to_string();
-            // Get the span only for the name of the variable (I hope the path
-            // is only ever a variable name, but who knows?).
-            let sub_span = self.span.span_for_last_ident(p.span);
-            // Rust uses the id of the pattern for var lookups, so we'll use it too.
-            self.fmt.variable_str(p.span,
-                                  sub_span,
-                                  id,
-                                  &path_to_string(p),
-                                  &value,
-                                  &typ);
-        }
+        self.process_var_decl(&l.pat, value);
 
         // Just walk the initialiser and type (don't want to walk the pattern again).
-        visit::walk_ty_opt(self, &l.ty);
-        visit::walk_expr_opt(self, &l.init);
+        walk_list!(self, visit_ty, &l.ty);
+        walk_list!(self, visit_expr, &l.init);
     }
 }
+
index 9c6f1a0eb5a89bd6794b558bfea4c570af0d14a5..af9f3e4896d2c8b3cbacf9323bbb73d6a5259972 100644 (file)
@@ -10,7 +10,7 @@
 
 use middle::ty;
 use middle::def;
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::DefId;
 
 use std::env;
 use std::fs::{self, File};
@@ -18,9 +18,8 @@ use std::path::{Path, PathBuf};
 
 use rustc_front;
 use rustc::front::map::NodeItem;
-use rustc_front::hir;
+use rustc_front::{hir, lowering};
 
-use syntax::attr;
 use syntax::ast::{self, NodeId};
 use syntax::ast_util;
 use syntax::codemap::*;
@@ -38,6 +37,7 @@ mod dump_csv;
 
 pub struct SaveContext<'l, 'tcx: 'l> {
     tcx: &'l ty::ctxt<'tcx>,
+    lcx: &'l lowering::LoweringContext<'l>,
     span_utils: SpanUtils<'l>,
 }
 
@@ -176,15 +176,22 @@ pub struct MethodCallData {
 
 
 impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
-    pub fn new(tcx: &'l ty::ctxt<'tcx>) -> SaveContext<'l, 'tcx> {
+    pub fn new(tcx: &'l ty::ctxt<'tcx>,
+               lcx: &'l lowering::LoweringContext<'l>)
+               -> SaveContext<'l, 'tcx> {
         let span_utils = SpanUtils::new(&tcx.sess);
-        SaveContext::from_span_utils(tcx, span_utils)
+        SaveContext::from_span_utils(tcx, lcx, span_utils)
     }
 
     pub fn from_span_utils(tcx: &'l ty::ctxt<'tcx>,
+                           lcx: &'l lowering::LoweringContext<'l>,
                            span_utils: SpanUtils<'l>)
                            -> SaveContext<'l, 'tcx> {
-        SaveContext { tcx: tcx, span_utils: span_utils }
+        SaveContext {
+            tcx: tcx,
+            lcx: lcx,
+            span_utils: span_utils,
+        }
     }
 
     // List external crates used by the current crate.
@@ -192,7 +199,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
         let mut result = Vec::new();
 
         self.tcx.sess.cstore.iter_crate_data(|n, cmd| {
-            result.push(CrateData { name: cmd.name.clone(), number: n });
+            result.push(CrateData {
+                name: cmd.name.clone(),
+                number: n,
+            });
         });
 
         result
@@ -289,10 +299,12 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     // Common case impl for a struct or something basic.
                     ast::TyPath(None, ref path) => {
                         sub_span = self.span_utils.sub_span_for_type_name(path.span).unwrap();
-                        type_data = self.lookup_ref_id(typ.id).map(|id| TypeRefData {
-                            span: sub_span,
-                            scope: parent,
-                            ref_id: id,
+                        type_data = self.lookup_ref_id(typ.id).map(|id| {
+                            TypeRefData {
+                                span: sub_span,
+                                scope: parent,
+                                ref_id: id,
+                            }
                         });
                     }
                     _ => {
@@ -302,8 +314,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     }
                 }
 
-                let trait_data =
-                    trait_ref.as_ref().and_then(|tr| self.get_trait_ref_data(tr, parent));
+                let trait_data = trait_ref.as_ref()
+                                          .and_then(|tr| self.get_trait_ref_data(tr, parent));
 
                 Data::ImplData(ImplData {
                     id: item.id,
@@ -323,11 +335,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
     pub fn get_field_data(&self, field: &ast::StructField, scope: NodeId) -> Option<VariableData> {
         match field.node.kind {
             ast::NamedField(ident, _) => {
-                let qualname = format!("::{}::{}",
-                                       self.tcx.map.path_to_string(scope),
-                                       ident);
-                let typ = self.tcx.node_types().get(&field.node.id).unwrap()
-                                               .to_string();
+                let qualname = format!("::{}::{}", self.tcx.map.path_to_string(scope), ident);
+                let typ = self.tcx.node_types().get(&field.node.id).unwrap().to_string();
                 let sub_span = self.span_utils.sub_span_before_token(field.span, token::Colon);
                 Some(VariableData {
                     id: field.node.id,
@@ -348,19 +357,18 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
     pub fn get_method_data(&self, id: ast::NodeId, name: ast::Name, span: Span) -> FunctionData {
         // The qualname for a method is the trait name or name of the struct in an impl in
         // which the method is declared in, followed by the method's name.
-        let qualname = match self.tcx.impl_of_method(DefId::local(id)) {
-            Some(impl_id) => match self.tcx.map.get(impl_id.node) {
-                NodeItem(item) => {
+        let qualname = match self.tcx.impl_of_method(self.tcx.map.local_def_id(id)) {
+            Some(impl_id) => match self.tcx.map.get_if_local(impl_id) {
+                Some(NodeItem(item)) => {
                     match item.node {
                         hir::ItemImpl(_, _, _, _, ref ty, _) => {
                             let mut result = String::from("<");
                             result.push_str(&rustc_front::print::pprust::ty_to_string(&**ty));
 
-                            match self.tcx.trait_of_item(DefId::local(id)) {
+                            match self.tcx.trait_of_item(self.tcx.map.local_def_id(id)) {
                                 Some(def_id) => {
                                     result.push_str(" as ");
-                                    result.push_str(
-                                        &self.tcx.item_path_str(def_id));
+                                    result.push_str(&self.tcx.item_path_str(def_id));
                                 }
                                 None => {}
                             }
@@ -369,48 +377,56 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                         }
                         _ => {
                             self.tcx.sess.span_bug(span,
-                                &format!("Container {} for method {} not an impl?",
-                                         impl_id.node, id));
+                                                   &format!("Container {:?} for method {} not \
+                                                             an impl?",
+                                                            impl_id,
+                                                            id));
                         }
                     }
                 }
-                _ => {
+                r => {
                     self.tcx.sess.span_bug(span,
-                        &format!("Container {} for method {} is not a node item {:?}",
-                                 impl_id.node, id, self.tcx.map.get(impl_id.node)));
+                                           &format!("Container {:?} for method {} is not a node \
+                                                     item {:?}",
+                                                    impl_id,
+                                                    id,
+                                                    r));
                 }
             },
-            None => match self.tcx.trait_of_item(DefId::local(id)) {
+            None => match self.tcx.trait_of_item(self.tcx.map.local_def_id(id)) {
                 Some(def_id) => {
-                    match self.tcx.map.get(def_id.node) {
-                        NodeItem(_) => {
+                    match self.tcx.map.get_if_local(def_id) {
+                        Some(NodeItem(_)) => {
                             format!("::{}", self.tcx.item_path_str(def_id))
                         }
-                        _ => {
+                        r => {
                             self.tcx.sess.span_bug(span,
-                                &format!("Could not find container {} for method {}",
-                                         def_id.node, id));
+                                                   &format!("Could not find container {:?} for \
+                                                             method {}, got {:?}",
+                                                            def_id,
+                                                            id,
+                                                            r));
                         }
                     }
                 }
                 None => {
                     self.tcx.sess.span_bug(span,
-                        &format!("Could not find container for method {}", id));
+                                           &format!("Could not find container for method {}", id));
                 }
             },
         };
 
         let qualname = format!("{}::{}", qualname, name);
 
-        let decl_id = self.tcx.trait_item_of_item(DefId::local(id))
-            .and_then(|new_id| {
-                let def_id = new_id.def_id();
-                if def_id.node != 0 && def_id != DefId::local(id) {
-                    Some(def_id)
-                } else {
-                    None
-                }
-            });
+        let def_id = self.tcx.map.local_def_id(id);
+        let decl_id = self.tcx.trait_item_of_item(def_id).and_then(|new_id| {
+            let new_def_id = new_id.def_id();
+            if new_def_id != def_id {
+                Some(new_def_id)
+            } else {
+                None
+            }
+        });
 
         let sub_span = self.span_utils.sub_span_after_keyword(span, keywords::Fn);
 
@@ -442,7 +458,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
     pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
         match expr.node {
             ast::ExprField(ref sub_ex, ident) => {
-                let hir_node = self.tcx.map.expect_expr(sub_ex.id);
+                let hir_node = lowering::lower_expr(self.lcx, sub_ex);
                 let ty = &self.tcx.expr_ty_adjusted(&hir_node).sty;
                 match *ty {
                     ty::TyStruct(def, _) => {
@@ -462,8 +478,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 }
             }
             ast::ExprStruct(ref path, _, _) => {
-                let hir_node = self.tcx.map.expect_expr(expr.id);
-                let ty = &self.tcx.expr_ty_adjusted(hir_node).sty;
+                let hir_node = lowering::lower_expr(self.lcx, expr);
+                let ty = &self.tcx.expr_ty_adjusted(&hir_node).sty;
                 match *ty {
                     ty::TyStruct(def, _) => {
                         let sub_span = self.span_utils.span_for_last_ident(path.span);
@@ -545,11 +561,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                     let ti = self.tcx.impl_or_trait_item(decl_id);
                     match ti.container() {
                         ty::TraitContainer(def_id) => {
-                            self.tcx.trait_items(def_id)
+                            self.tcx
+                                .trait_items(def_id)
                                 .iter()
-                                .find(|mr| {
-                                    mr.name() == ti.name() && self.trait_method_has_body(mr)
-                                })
+                                .find(|mr| mr.name() == ti.name() && self.trait_method_has_body(mr))
                                 .map(|mr| mr.def_id())
                         }
                         ty::ImplContainer(def_id) => {
@@ -558,9 +573,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                                            .unwrap()
                                            .iter()
                                            .find(|mr| {
-                                                self.tcx.impl_or_trait_item(mr.def_id()).name()
-                                                    == ti.name()
-                                            })
+                                               self.tcx.impl_or_trait_item(mr.def_id()).name() ==
+                                               ti.name()
+                                           })
                                            .unwrap()
                                            .def_id())
                         }
@@ -595,13 +610,13 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
 
     fn trait_method_has_body(&self, mr: &ty::ImplOrTraitItem) -> bool {
         let def_id = mr.def_id();
-        if def_id.krate != LOCAL_CRATE {
-            return false;
-        }
-
-        let trait_item = self.tcx.map.expect_trait_item(def_id.node);
-        if let hir::TraitItem_::MethodTraitItem(_, Some(_)) = trait_item.node {
-            true
+        if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
+            let trait_item = self.tcx.map.expect_trait_item(node_id);
+            if let hir::TraitItem_::MethodTraitItem(_, Some(_)) = trait_item.node {
+                true
+            } else {
+                false
+            }
         } else {
             false
         }
@@ -635,7 +650,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
         }
         let def = self.tcx.def_map.borrow().get(&ref_id).unwrap().full_def();
         match def {
-            def::DefPrimTy(_) => None,
+            def::DefPrimTy(_) | def::DefSelfTy(..) => None,
             _ => Some(def.def_id()),
         }
     }
@@ -666,10 +681,7 @@ impl<'v> Visitor<'v> for PathCollector {
 
         match p.node {
             ast::PatStruct(ref path, _, _) => {
-                self.collected_paths.push((p.id,
-                                           path.clone(),
-                                           ast::MutMutable,
-                                           recorder::TypeRef));
+                self.collected_paths.push((p.id, path.clone(), ast::MutMutable, recorder::TypeRef));
             }
             ast::PatEnum(ref path, _) |
             ast::PatQPath(_, ref path) => {
@@ -697,22 +709,17 @@ impl<'v> Visitor<'v> for PathCollector {
     }
 }
 
-pub fn process_crate(tcx: &ty::ctxt,
-                     krate: &ast::Crate,
-                     analysis: &ty::CrateAnalysis,
-                     odir: Option<&Path>) {
+pub fn process_crate<'l, 'tcx>(tcx: &'l ty::ctxt<'tcx>,
+                               lcx: &'l lowering::LoweringContext<'l>,
+                               krate: &ast::Crate,
+                               analysis: &ty::CrateAnalysis,
+                               cratename: &str,
+                               odir: Option<&Path>) {
     if generated_code(krate.span) {
         return;
     }
 
     assert!(analysis.glob_map.is_some());
-    let cratename = match attr::find_crate_name(&krate.attrs) {
-        Some(name) => name.to_string(),
-        None => {
-            info!("Could not find crate name, using 'unknown_crate'");
-            String::from("unknown_crate")
-        }
-    };
 
     info!("Dumping crate {}", cratename);
 
@@ -727,7 +734,8 @@ pub fn process_crate(tcx: &ty::ctxt,
 
     if let Err(e) = fs::create_dir_all(&root_path) {
         tcx.sess.err(&format!("Could not create directory {}: {}",
-                              root_path.display(), e));
+                              root_path.display(),
+                              e));
     }
 
     {
@@ -736,7 +744,7 @@ pub fn process_crate(tcx: &ty::ctxt,
     }
 
     // Create output file.
-    let mut out_name = cratename.clone();
+    let mut out_name = cratename.to_owned();
     out_name.push_str(".csv");
     root_path.push(&out_name);
     let output_file = match File::create(&root_path) {
@@ -748,9 +756,9 @@ pub fn process_crate(tcx: &ty::ctxt,
     };
     root_path.pop();
 
-    let mut visitor = dump_csv::DumpCsvVisitor::new(tcx, analysis, output_file);
+    let mut visitor = dump_csv::DumpCsvVisitor::new(tcx, lcx, analysis, output_file);
 
-    visitor.dump_crate_info(&cratename, krate);
+    visitor.dump_crate_info(cratename, krate);
     visit::walk_crate(&mut visitor, krate);
 }
 
index f8e6864985364a8d72614de61e149859ac8fc5be..a32d8b1b761c540e839e3ad0df8bef5484d0e3ad 100644 (file)
@@ -13,7 +13,9 @@ pub use self::Row::*;
 use super::escape;
 use super::span_utils::SpanUtils;
 
-use middle::def_id::DefId;
+use metadata::cstore::LOCAL_CRATE;
+use middle::def_id::{CRATE_DEF_INDEX, DefId};
+use middle::ty;
 
 use std::io::Write;
 
@@ -21,7 +23,10 @@ use syntax::ast;
 use syntax::ast::NodeId;
 use syntax::codemap::*;
 
-const ZERO_DEF_ID: DefId = DefId { node: 0, krate: 0 };
+const CRATE_ROOT_DEF_ID: DefId = DefId {
+    krate: LOCAL_CRATE,
+    index: CRATE_DEF_INDEX,
+};
 
 pub struct Recorder {
     // output file
@@ -40,14 +45,17 @@ impl Recorder {
     pub fn dump_span(&mut self, su: SpanUtils, kind: &str, span: Span, _sub_span: Option<Span>) {
         assert!(self.dump_spans);
         let result = format!("span,kind,{},{},text,\"{}\"\n",
-                             kind, su.extent_str(span), escape(su.snippet(span)));
+                             kind,
+                             su.extent_str(span),
+                             escape(su.snippet(span)));
         self.record(&result[..]);
     }
 }
 
-pub struct FmtStrs<'a> {
+pub struct FmtStrs<'a, 'tcx: 'a> {
     pub recorder: Box<Recorder>,
     span: SpanUtils<'a>,
+    tcx: &'a ty::ctxt<'tcx>,
 }
 
 macro_rules! s { ($e:expr) => { format!("{}", $e) }}
@@ -90,9 +98,30 @@ pub enum Row {
     FnRef,
 }
 
-impl<'a> FmtStrs<'a> {
-    pub fn new(rec: Box<Recorder>, span: SpanUtils<'a>) -> FmtStrs<'a> {
-        FmtStrs { recorder: rec, span: span }
+impl<'a, 'tcx: 'a> FmtStrs<'a, 'tcx> {
+    pub fn new(rec: Box<Recorder>,
+               span: SpanUtils<'a>,
+               tcx: &'a ty::ctxt<'tcx>)
+               -> FmtStrs<'a, 'tcx> {
+        FmtStrs {
+            recorder: rec,
+            span: span,
+            tcx: tcx,
+        }
+    }
+
+    // Emitted ids are used to cross-reference items across crates. DefIds and
+    // NodeIds do not usually correspond in any way. The strategy is to use the
+    // index from the DefId as a crate-local id. However, within a crate, DefId
+    // indices and NodeIds can overlap. So, we must adjust the NodeIds. If an
+    // item can be identified by a DefId as well as a NodeId, then we use the
+    // DefId index as the id. If it can't, then we have to use the NodeId, but
+    // need to adjust it so it will not clash with any possible DefId index.
+    fn normalize_node_id(&self, id: NodeId) -> usize {
+        match self.tcx.map.opt_local_def_id(id) {
+            Some(id) => id.index.as_usize(),
+            None => id as usize + self.tcx.map.num_local_def_ids()
+        }
     }
 
     // A map from kind of item to a tuple of
@@ -103,52 +132,93 @@ impl<'a> FmtStrs<'a> {
     fn lookup_row(r: Row) -> (&'static str, Vec<&'static str>, bool, bool) {
         match r {
             Variable => ("variable",
-                         vec!("id","name","qualname","value","type","scopeid"),
+                         vec!("id", "name", "qualname", "value", "type", "scopeid"),
                          true,
                          true),
-            Enum => ("enum", vec!("id","qualname","scopeid","value"), true, true),
+            Enum => ("enum",
+                     vec!("id", "qualname", "scopeid", "value"),
+                     true,
+                     true),
             Variant => ("variant",
-                        vec!("id","name","qualname","type","value","scopeid"),
+                        vec!("id", "name", "qualname", "type", "value", "scopeid"),
                         true,
                         true),
             VariantStruct => ("variant_struct",
-                              vec!("id","ctor_id","qualname","type","value","scopeid"),
+                              vec!("id", "ctor_id", "qualname", "type", "value", "scopeid"),
                               true,
                               true),
             Function => ("function",
-                         vec!("id","qualname","declid","declidcrate","scopeid"),
+                         vec!("id", "qualname", "declid", "declidcrate", "scopeid"),
                          true,
                          true),
-            MethodDecl => ("method_decl", vec!("id","qualname","scopeid"), true, true),
-            Struct => ("struct", vec!("id","ctor_id","qualname","scopeid","value"), true, true),
-            Trait => ("trait", vec!("id","qualname","scopeid","value"), true, true),
+            MethodDecl => ("method_decl",
+                           vec!("id", "qualname", "scopeid"),
+                           true,
+                           true),
+            Struct => ("struct",
+                       vec!("id", "ctor_id", "qualname", "scopeid", "value"),
+                       true,
+                       true),
+            Trait => ("trait",
+                      vec!("id", "qualname", "scopeid", "value"),
+                      true,
+                      true),
             Impl => ("impl",
-                     vec!("id","refid","refidcrate","traitid","traitidcrate","scopeid"),
+                     vec!("id",
+                          "refid",
+                          "refidcrate",
+                          "traitid",
+                          "traitidcrate",
+                          "scopeid"),
                      true,
                      true),
-            Module => ("module", vec!("id","qualname","scopeid","def_file"), true, false),
-            UseAlias => ("use_alias", vec!("id","refid","refidcrate","name","scopeid"), true, true),
-            UseGlob => ("use_glob", vec!("id","value","scopeid"), true, true),
+            Module => ("module",
+                       vec!("id", "qualname", "scopeid", "def_file"),
+                       true,
+                       false),
+            UseAlias => ("use_alias",
+                         vec!("id", "refid", "refidcrate", "name", "scopeid"),
+                         true,
+                         true),
+            UseGlob => ("use_glob", vec!("id", "value", "scopeid"), true, true),
             ExternCrate => ("extern_crate",
-                            vec!("id","name","location","crate","scopeid"),
+                            vec!("id", "name", "location", "crate", "scopeid"),
                             true,
                             true),
             Inheritance => ("inheritance",
-                            vec!("base","basecrate","derived","derivedcrate"),
+                            vec!("base", "basecrate", "derived", "derivedcrate"),
                             true,
                             false),
             MethodCall => ("method_call",
-                           vec!("refid","refidcrate","declid","declidcrate","scopeid"),
+                           vec!("refid", "refidcrate", "declid", "declidcrate", "scopeid"),
                            true,
                            true),
-            Typedef => ("typedef", vec!("id","qualname","value"), true, true),
-            ExternalCrate => ("external_crate", vec!("name","crate","file_name"), false, false),
+            Typedef => ("typedef", vec!("id", "qualname", "value"), true, true),
+            ExternalCrate => ("external_crate",
+                              vec!("name", "crate", "file_name"),
+                              false,
+                              false),
             Crate => ("crate", vec!("name"), true, false),
-            FnCall => ("fn_call", vec!("refid","refidcrate","qualname","scopeid"), true, true),
-            ModRef => ("mod_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true),
-            VarRef => ("var_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true),
-            TypeRef => ("type_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true),
-            FnRef => ("fn_ref", vec!("refid","refidcrate","qualname","scopeid"), true, true),
+            FnCall => ("fn_call",
+                       vec!("refid", "refidcrate", "qualname", "scopeid"),
+                       true,
+                       true),
+            ModRef => ("mod_ref",
+                       vec!("refid", "refidcrate", "qualname", "scopeid"),
+                       true,
+                       true),
+            VarRef => ("var_ref",
+                       vec!("refid", "refidcrate", "qualname", "scopeid"),
+                       true,
+                       true),
+            TypeRef => ("type_ref",
+                        vec!("refid", "refidcrate", "qualname", "scopeid"),
+                        true,
+                        true),
+            FnRef => ("fn_ref",
+                      vec!("refid", "refidcrate", "qualname", "scopeid"),
+                      true,
+                      true),
         }
     }
 
@@ -159,9 +229,12 @@ impl<'a> FmtStrs<'a> {
                            span: Span)
                            -> Option<String> {
         if values.len() != fields.len() {
-            self.span.sess.span_bug(span, &format!(
-                "Mismatch between length of fields for '{}', expected '{}', found '{}'",
-                kind, fields.len(), values.len()));
+            self.span.sess.span_bug(span,
+                                    &format!("Mismatch between length of fields for '{}', \
+                                              expected '{}', found '{}'",
+                                             kind,
+                                             fields.len(),
+                                             values.len()));
         }
 
         let values = values.iter().map(|s| {
@@ -175,19 +248,21 @@ impl<'a> FmtStrs<'a> {
 
         let pairs = fields.iter().zip(values);
         let strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(String::from(v))));
-        Some(strs.fold(String::new(), |mut s, ss| {
-            s.push_str(&ss[..]);
-            s
-        }))
+        Some(strs.fold(String::new(),
+                       |mut s, ss| {
+                           s.push_str(&ss[..]);
+                           s
+                       }))
     }
 
     pub fn record_without_span(&mut self, kind: Row, values: Vec<String>, span: Span) {
         let (label, ref fields, needs_span, dump_spans) = FmtStrs::lookup_row(kind);
 
         if needs_span {
-            self.span.sess.span_bug(span, &format!(
-                "Called record_without_span for '{}' which does requires a span",
-                label));
+            self.span.sess.span_bug(span,
+                                    &format!("Called record_without_span for '{}' which does \
+                                              requires a span",
+                                             label));
         }
         assert!(!dump_spans);
 
@@ -215,25 +290,26 @@ impl<'a> FmtStrs<'a> {
 
         if self.recorder.dump_spans {
             if dump_spans {
-                self.recorder.dump_span(self.span.clone(),
-                                        label,
-                                        span,
-                                        Some(sub_span));
+                self.recorder.dump_span(self.span.clone(), label, span, Some(sub_span));
             }
             return;
         }
 
         if !needs_span {
             self.span.sess.span_bug(span,
-                                    &format!("Called record_with_span for '{}' \
-                                              which does not require a span", label));
+                                    &format!("Called record_with_span for '{}' which does not \
+                                              require a span",
+                                             label));
         }
 
         let values_str = match self.make_values_str(label, fields, values, span) {
             Some(vs) => vs,
             None => return,
         };
-        let result = format!("{},{}{}\n", label, self.span.extent_str(sub_span), values_str);
+        let result = format!("{},{}{}\n",
+                             label,
+                             self.span.extent_str(sub_span),
+                             values_str);
         self.recorder.record(&result[..]);
     }
 
@@ -265,6 +341,7 @@ impl<'a> FmtStrs<'a> {
         let mut qualname = String::from(name);
         qualname.push_str("$");
         qualname.push_str(&id.to_string());
+        let id = self.normalize_node_id(id);
         self.check_and_record(Variable,
                               span,
                               sub_span,
@@ -282,6 +359,7 @@ impl<'a> FmtStrs<'a> {
         let mut qualname = String::from(fn_name);
         qualname.push_str("::");
         qualname.push_str(name);
+        let id = self.normalize_node_id(id);
         self.check_and_record(Variable,
                               span,
                               sub_span,
@@ -298,6 +376,8 @@ impl<'a> FmtStrs<'a> {
                       value: &str,
                       typ: &str,
                       scope_id: NodeId) {
+        let id = self.normalize_node_id(id);
+        let scope_id = self.normalize_node_id(scope_id);
         self.check_and_record(Variable,
                               span,
                               sub_span,
@@ -312,6 +392,8 @@ impl<'a> FmtStrs<'a> {
                      qualname: &str,
                      typ: &str,
                      scope_id: NodeId) {
+        let id = self.normalize_node_id(id);
+        let scope_id = self.normalize_node_id(scope_id);
         self.check_and_record(Variable,
                               span,
                               sub_span,
@@ -325,10 +407,9 @@ impl<'a> FmtStrs<'a> {
                     name: &str,
                     scope_id: NodeId,
                     value: &str) {
-        self.check_and_record(Enum,
-                              span,
-                              sub_span,
-                              svec!(id, name, scope_id, value));
+        let id = self.normalize_node_id(id);
+        let scope_id = self.normalize_node_id(scope_id);
+        self.check_and_record(Enum, span, sub_span, svec!(id, name, scope_id, value));
     }
 
     pub fn tuple_variant_str(&mut self,
@@ -340,6 +421,8 @@ impl<'a> FmtStrs<'a> {
                              typ: &str,
                              val: &str,
                              scope_id: NodeId) {
+        let id = self.normalize_node_id(id);
+        let scope_id = self.normalize_node_id(scope_id);
         self.check_and_record(Variant,
                               span,
                               sub_span,
@@ -355,6 +438,9 @@ impl<'a> FmtStrs<'a> {
                               typ: &str,
                               val: &str,
                               scope_id: NodeId) {
+        let id = self.normalize_node_id(id);
+        let scope_id = self.normalize_node_id(scope_id);
+        let ctor_id = self.normalize_node_id(ctor_id);
         self.check_and_record(VariantStruct,
                               span,
                               sub_span,
@@ -367,6 +453,8 @@ impl<'a> FmtStrs<'a> {
                   id: NodeId,
                   name: &str,
                   scope_id: NodeId) {
+        let id = self.normalize_node_id(id);
+        let scope_id = self.normalize_node_id(scope_id);
         self.check_and_record(Function,
                               span,
                               sub_span,
@@ -380,14 +468,17 @@ impl<'a> FmtStrs<'a> {
                       name: &str,
                       decl_id: Option<DefId>,
                       scope_id: NodeId) {
+        let id = self.normalize_node_id(id);
+        let scope_id = self.normalize_node_id(scope_id);
         let values = match decl_id {
-            Some(decl_id) => svec!(id, name, decl_id.node, decl_id.krate, scope_id),
+            Some(decl_id) => svec!(id,
+                                   name,
+                                   decl_id.index.as_usize(),
+                                   decl_id.krate,
+                                   scope_id),
             None => svec!(id, name, "", "", scope_id),
         };
-        self.check_and_record(Function,
-                              span,
-                              sub_span,
-                              values);
+        self.check_and_record(Function, span, sub_span, values);
     }
 
     pub fn method_decl_str(&mut self,
@@ -396,10 +487,9 @@ impl<'a> FmtStrs<'a> {
                            id: NodeId,
                            name: &str,
                            scope_id: NodeId) {
-        self.check_and_record(MethodDecl,
-                              span,
-                              sub_span,
-                              svec!(id, name, scope_id));
+        let id = self.normalize_node_id(id);
+        let scope_id = self.normalize_node_id(scope_id);
+        self.check_and_record(MethodDecl, span, sub_span, svec!(id, name, scope_id));
     }
 
     pub fn struct_str(&mut self,
@@ -410,6 +500,9 @@ impl<'a> FmtStrs<'a> {
                       name: &str,
                       scope_id: NodeId,
                       value: &str) {
+        let id = self.normalize_node_id(id);
+        let scope_id = self.normalize_node_id(scope_id);
+        let ctor_id = self.normalize_node_id(ctor_id);
         self.check_and_record(Struct,
                               span,
                               sub_span,
@@ -423,10 +516,9 @@ impl<'a> FmtStrs<'a> {
                      name: &str,
                      scope_id: NodeId,
                      value: &str) {
-        self.check_and_record(Trait,
-                              span,
-                              sub_span,
-                              svec!(id, name, scope_id, value));
+        let id = self.normalize_node_id(id);
+        let scope_id = self.normalize_node_id(scope_id);
+        self.check_and_record(Trait, span, sub_span, svec!(id, name, scope_id, value));
     }
 
     pub fn impl_str(&mut self,
@@ -436,15 +528,17 @@ impl<'a> FmtStrs<'a> {
                     ref_id: Option<DefId>,
                     trait_id: Option<DefId>,
                     scope_id: NodeId) {
-        let ref_id = ref_id.unwrap_or(ZERO_DEF_ID);
-        let trait_id = trait_id.unwrap_or(ZERO_DEF_ID);
+        let id = self.normalize_node_id(id);
+        let scope_id = self.normalize_node_id(scope_id);
+        let ref_id = ref_id.unwrap_or(CRATE_ROOT_DEF_ID);
+        let trait_id = trait_id.unwrap_or(CRATE_ROOT_DEF_ID);
         self.check_and_record(Impl,
                               span,
                               sub_span,
                               svec!(id,
-                                    ref_id.node,
+                                    ref_id.index.as_usize(),
                                     ref_id.krate,
-                                    trait_id.node,
+                                    trait_id.index.as_usize(),
                                     trait_id.krate,
                                     scope_id));
     }
@@ -456,6 +550,8 @@ impl<'a> FmtStrs<'a> {
                    name: &str,
                    parent: NodeId,
                    filename: &str) {
+        let id = self.normalize_node_id(id);
+        let parent = self.normalize_node_id(parent);
         self.check_and_record(Module,
                               span,
                               sub_span,
@@ -469,14 +565,13 @@ impl<'a> FmtStrs<'a> {
                          mod_id: Option<DefId>,
                          name: &str,
                          parent: NodeId) {
-        let (mod_node, mod_crate) = match mod_id {
-            Some(mod_id) => (mod_id.node, mod_id.krate),
-            None => (0, 0),
-        };
+        let id = self.normalize_node_id(id);
+        let parent = self.normalize_node_id(parent);
+        let mod_id = mod_id.unwrap_or(CRATE_ROOT_DEF_ID);
         self.check_and_record(UseAlias,
                               span,
                               sub_span,
-                              svec!(id, mod_node, mod_crate, name, parent));
+                              svec!(id, mod_id.index.as_usize(), mod_id.krate, name, parent));
     }
 
     pub fn use_glob_str(&mut self,
@@ -485,10 +580,9 @@ impl<'a> FmtStrs<'a> {
                         id: NodeId,
                         values: &str,
                         parent: NodeId) {
-        self.check_and_record(UseGlob,
-                              span,
-                              sub_span,
-                              svec!(id, values, parent));
+        let id = self.normalize_node_id(id);
+        let parent = self.normalize_node_id(parent);
+        self.check_and_record(UseGlob, span, sub_span, svec!(id, values, parent));
     }
 
     pub fn extern_crate_str(&mut self,
@@ -499,6 +593,8 @@ impl<'a> FmtStrs<'a> {
                             name: &str,
                             loc: &str,
                             parent: NodeId) {
+        let id = self.normalize_node_id(id);
+        let parent = self.normalize_node_id(parent);
         self.check_and_record(ExternCrate,
                               span,
                               sub_span,
@@ -510,13 +606,11 @@ impl<'a> FmtStrs<'a> {
                        sub_span: Option<Span>,
                        base_id: DefId,
                        deriv_id: NodeId) {
+        let deriv_id = self.normalize_node_id(deriv_id);
         self.check_and_record(Inheritance,
                               span,
                               sub_span,
-                              svec!(base_id.node,
-                                    base_id.krate,
-                                    deriv_id,
-                                    0));
+                              svec!(base_id.index.as_usize(), base_id.krate, deriv_id, 0));
     }
 
     pub fn fn_call_str(&mut self,
@@ -524,10 +618,11 @@ impl<'a> FmtStrs<'a> {
                        sub_span: Option<Span>,
                        id: DefId,
                        scope_id: NodeId) {
+        let scope_id = self.normalize_node_id(scope_id);
         self.check_and_record(FnCall,
                               span,
                               sub_span,
-                              svec!(id.node, id.krate, "", scope_id));
+                              svec!(id.index.as_usize(), id.krate, "", scope_id));
     }
 
     pub fn meth_call_str(&mut self,
@@ -536,25 +631,21 @@ impl<'a> FmtStrs<'a> {
                          defid: Option<DefId>,
                          declid: Option<DefId>,
                          scope_id: NodeId) {
-        let (dfn, dfk) = match defid {
-            Some(defid) => (defid.node, defid.krate),
-            None => (0, 0),
-        };
+        let scope_id = self.normalize_node_id(scope_id);
+        let defid = defid.unwrap_or(CRATE_ROOT_DEF_ID);
         let (dcn, dck) = match declid {
-            Some(declid) => (s!(declid.node), s!(declid.krate)),
+            Some(declid) => (s!(declid.index.as_usize()), s!(declid.krate)),
             None => ("".to_string(), "".to_string()),
         };
         self.check_and_record(MethodCall,
                               span,
                               sub_span,
-                              svec!(dfn, dfk, dcn, dck, scope_id));
+                              svec!(defid.index.as_usize(), defid.krate, dcn, dck, scope_id));
     }
 
     pub fn sub_mod_ref_str(&mut self, span: Span, sub_span: Span, qualname: &str, parent: NodeId) {
-        self.record_with_span(ModRef,
-                              span,
-                              sub_span,
-                              svec!(0, 0, qualname, parent));
+        let parent = self.normalize_node_id(parent);
+        self.record_with_span(ModRef, span, sub_span, svec!(0, 0, qualname, parent));
     }
 
     pub fn typedef_str(&mut self,
@@ -563,17 +654,12 @@ impl<'a> FmtStrs<'a> {
                        id: NodeId,
                        qualname: &str,
                        value: &str) {
-        self.check_and_record(Typedef,
-                              span,
-                              sub_span,
-                              svec!(id, qualname, value));
+        let id = self.normalize_node_id(id);
+        self.check_and_record(Typedef, span, sub_span, svec!(id, qualname, value));
     }
 
     pub fn crate_str(&mut self, span: Span, name: &str) {
-        self.record_with_span(Crate,
-                              span,
-                              span,
-                              svec!(name));
+        self.record_with_span(Crate, span, span, svec!(name));
     }
 
     pub fn external_crate_str(&mut self, span: Span, name: &str, num: ast::CrateNum) {
@@ -584,10 +670,7 @@ impl<'a> FmtStrs<'a> {
     }
 
     pub fn sub_type_ref_str(&mut self, span: Span, sub_span: Span, qualname: &str) {
-        self.record_with_span(TypeRef,
-                              span,
-                              sub_span,
-                              svec!(0, 0, qualname, 0));
+        self.record_with_span(TypeRef, span, sub_span, svec!(0, 0, qualname, 0));
     }
 
     // A slightly generic function for a reference to an item of any kind.
@@ -597,9 +680,10 @@ impl<'a> FmtStrs<'a> {
                    sub_span: Option<Span>,
                    id: DefId,
                    scope_id: NodeId) {
+        let scope_id = self.normalize_node_id(scope_id);
         self.check_and_record(kind,
                               span,
                               sub_span,
-                              svec!(id.node, id.krate, "", scope_id));
+                              svec!(id.index.as_usize(), id.krate, "", scope_id));
     }
 }
index 5647e88658a3b9cb934a397f1054313c8b089128..aa1976804382d69635a8e6d4b784b3312681276e 100644 (file)
@@ -29,10 +29,14 @@ pub struct SpanUtils<'a> {
 
 impl<'a> SpanUtils<'a> {
     pub fn new(sess: &'a Session) -> SpanUtils<'a> {
-        SpanUtils { sess: sess, err_count: Cell::new(0) }
+        SpanUtils {
+            sess: sess,
+            err_count: Cell::new(0),
+        }
     }
 
     // Standard string for extents/location.
+    #[rustfmt_skip]
     pub fn extent_str(&self, span: Span) -> String {
         let lo_loc = self.sess.codemap().lookup_char_pos(span.lo);
         let hi_loc = self.sess.codemap().lookup_char_pos(span.hi);
@@ -54,7 +58,9 @@ impl<'a> SpanUtils<'a> {
         let loc = self.sess.codemap().lookup_char_pos(span.lo);
         assert!(!generated_code(span),
                 "generated code; we should not be processing this `{}` in {}, line {}",
-                 self.snippet(span), loc.file.name, loc.line);
+                self.snippet(span),
+                loc.file.name,
+                loc.line);
 
         match sub_span {
             None => None,
@@ -86,8 +92,9 @@ impl<'a> SpanUtils<'a> {
         // the codemap as a new filemap. This is mostly OK, but means we should
         // not iterate over the codemap. Also, any spans over the new filemap
         // are incompatible with spans over other filemaps.
-        let filemap = self.sess.codemap().new_filemap(String::from("<anon-dxr>"),
-                                                      self.snippet(span));
+        let filemap = self.sess
+                          .codemap()
+                          .new_filemap(String::from("<anon-dxr>"), self.snippet(span));
         let s = self.sess;
         lexer::StringReader::new(s.diagnostic(), filemap)
     }
@@ -213,8 +220,11 @@ impl<'a> SpanUtils<'a> {
         if bracket_count != 0 {
             let loc = self.sess.codemap().lookup_char_pos(span.lo);
             self.sess.span_bug(span,
-                &format!("Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}",
-                        self.snippet(span), loc.file.name, loc.line));
+                               &format!("Mis-counted brackets when breaking path? Parsing '{}' \
+                                         in {}, line {}",
+                                        self.snippet(span),
+                                        loc.file.name,
+                                        loc.line));
         }
         if result.is_none() && prev.tok.is_ident() && bracket_count == 0 {
             return self.make_sub_span(span, Some(prev.sp));
@@ -239,9 +249,12 @@ impl<'a> SpanUtils<'a> {
             if ts.tok == token::Eof {
                 if bracket_count != 0 {
                     let loc = self.sess.codemap().lookup_char_pos(span.lo);
-                    self.sess.span_bug(span, &format!(
-                        "Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}",
-                         self.snippet(span), loc.file.name, loc.line));
+                    self.sess.span_bug(span,
+                                       &format!("Mis-counted brackets when breaking path? \
+                                                 Parsing '{}' in {}, line {}",
+                                                self.snippet(span),
+                                                loc.file.name,
+                                                loc.line));
                 }
                 return result
             }
@@ -355,8 +368,11 @@ impl<'a> SpanUtils<'a> {
     pub fn report_span_err(&self, kind: &str, span: Span) {
         let loc = self.sess.codemap().lookup_char_pos(span.lo);
         info!("({}) Could not find sub_span in `{}` in {}, line {}",
-              kind, self.snippet(span), loc.file.name, loc.line);
-        self.err_count.set(self.err_count.get()+1);
+              kind,
+              self.snippet(span),
+              loc.file.name,
+              loc.line);
+        self.err_count.set(self.err_count.get() + 1);
         if self.err_count.get() > 1000 {
             self.sess.bug("span errors reached 1000, giving up");
         }
index c6866004df949254f515bac2b5d81b2154c9e845..566b494f66175020cb8d7b8826192451c57a05fe 100644 (file)
@@ -226,6 +226,7 @@ use std::fmt;
 use std::rc::Rc;
 use rustc_front::hir;
 use syntax::ast::{self, DUMMY_NODE_ID, NodeId};
+use syntax::ext::mtwt;
 use syntax::codemap::Span;
 use rustc_front::fold::Folder;
 use syntax::ptr::P;
@@ -275,19 +276,30 @@ impl<'a, 'tcx> Opt<'a, 'tcx> {
     }
 
     fn trans<'blk>(&self, mut bcx: Block<'blk, 'tcx>) -> OptResult<'blk, 'tcx> {
+        use trans::consts::TrueConst::Yes;
         let _icx = push_ctxt("match::trans_opt");
         let ccx = bcx.ccx();
         match *self {
             ConstantValue(ConstantExpr(lit_expr), _) => {
                 let lit_ty = bcx.tcx().node_id_to_type(lit_expr.id);
-                let (llval, _) = consts::const_expr(ccx, &*lit_expr, bcx.fcx.param_substs, None);
+                let expr = consts::const_expr(ccx, &*lit_expr, bcx.fcx.param_substs, None, Yes);
+                let llval = match expr {
+                    Ok((llval, _)) => llval,
+                    Err(err) => bcx.ccx().sess().span_fatal(lit_expr.span, &err.description()),
+                };
                 let lit_datum = immediate_rvalue(llval, lit_ty);
                 let lit_datum = unpack_datum!(bcx, lit_datum.to_appropriate_datum(bcx));
                 SingleResult(Result::new(bcx, lit_datum.val))
             }
             ConstantRange(ConstantExpr(ref l1), ConstantExpr(ref l2), _) => {
-                let (l1, _) = consts::const_expr(ccx, &**l1, bcx.fcx.param_substs, None);
-                let (l2, _) = consts::const_expr(ccx, &**l2, bcx.fcx.param_substs, None);
+                let l1 = match consts::const_expr(ccx, &**l1, bcx.fcx.param_substs, None, Yes) {
+                    Ok((l1, _)) => l1,
+                    Err(err) => bcx.ccx().sess().span_fatal(l1.span, &err.description()),
+                };
+                let l2 = match consts::const_expr(ccx, &**l2, bcx.fcx.param_substs, None, Yes) {
+                    Ok((l2, _)) => l2,
+                    Err(err) => bcx.ccx().sess().span_fatal(l2.span, &err.description()),
+                };
                 RangeResult(Result::new(bcx, l1), Result::new(bcx, l2))
             }
             Variant(disr_val, ref repr, _, _) => {
@@ -375,7 +387,7 @@ pub struct BindingInfo<'tcx> {
     pub ty: Ty<'tcx>,
 }
 
-type BindingsMap<'tcx> = FnvHashMap<ast::Ident, BindingInfo<'tcx>>;
+type BindingsMap<'tcx> = FnvHashMap<ast::Name, BindingInfo<'tcx>>;
 
 struct ArmData<'p, 'blk, 'tcx: 'blk> {
     bodycx: Block<'blk, 'tcx>,
@@ -390,7 +402,7 @@ struct ArmData<'p, 'blk, 'tcx: 'blk> {
 struct Match<'a, 'p: 'a, 'blk: 'a, 'tcx: 'blk> {
     pats: Vec<&'p hir::Pat>,
     data: &'a ArmData<'p, 'blk, 'tcx>,
-    bound_ptrs: Vec<(ast::Ident, ValueRef)>,
+    bound_ptrs: Vec<(ast::Name, ValueRef)>,
     // Thread along renamings done by the check_match::StaticInliner, so we can
     // map back to original NodeIds
     pat_renaming_map: Option<&'a FnvHashMap<(NodeId, Span), NodeId>>
@@ -464,7 +476,7 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         loop {
             pat = match pat.node {
                 hir::PatIdent(_, ref path, Some(ref inner)) => {
-                    bound_ptrs.push((path.node, val.val));
+                    bound_ptrs.push((mtwt::resolve(path.node), val.val));
                     &**inner
                 },
                 _ => break
@@ -505,7 +517,7 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
             match this.node {
                 hir::PatIdent(_, ref path, None) => {
                     if pat_is_binding(dm, &*this) {
-                        bound_ptrs.push((path.node, val.val));
+                        bound_ptrs.push((mtwt::resolve(path.node), val.val));
                     }
                 }
                 hir::PatVec(ref before, Some(ref slice), ref after) => {
@@ -513,7 +525,7 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
                         let subslice_val = bind_subslice_pat(
                             bcx, this.id, val,
                             before.len(), after.len());
-                        bound_ptrs.push((path.node, subslice_val));
+                        bound_ptrs.push((mtwt::resolve(path.node), subslice_val));
                     }
                 }
                 _ => {}
@@ -905,7 +917,7 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                 compare_str(cx, lhs_data, lhs_len, rhs_data, rhs_len, rhs_t, debug_loc)
             }
             ty::TyArray(ty, _) | ty::TySlice(ty) => match ty.sty {
-                ty::TyUint(hir::TyU8) => {
+                ty::TyUint(ast::TyU8) => {
                     // NOTE: cast &[u8] and &[u8; N] to &str and abuse the str_eq lang item,
                     // which calls memcmp().
                     let pat_len = val_ty(rhs).element_type().array_length();
@@ -943,7 +955,7 @@ fn insert_lllocals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                bindings_map: &BindingsMap<'tcx>,
                                cs: Option<cleanup::ScopeId>)
                                -> Block<'blk, 'tcx> {
-    for (&ident, &binding_info) in bindings_map {
+    for (&name, &binding_info) in bindings_map {
         let (llval, aliases_other_state) = match binding_info.trmode {
             // By value mut binding for a copy type: load from the ptr
             // into the matched value and copy to our alloca
@@ -963,8 +975,8 @@ fn insert_lllocals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                         // leaving the remainder of the tuple `(_,
                         // D(B))` still to be dropped in the future.
                         //
-                        // Thus, here we must must zero the place that
-                        // we are moving *from*, because we do not yet
+                        // Thus, here we must zero the place that we
+                        // are moving *from*, because we do not yet
                         // track drop flags for a fragmented parent
                         // match input expression.
                         //
@@ -1021,7 +1033,7 @@ fn insert_lllocals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 
         debug!("binding {} to {}", binding_info.id, bcx.val_to_string(llval));
         bcx.fcx.lllocals.borrow_mut().insert(binding_info.id, datum);
-        debuginfo::create_match_binding_metadata(bcx, ident.name, binding_info);
+        debuginfo::create_match_binding_metadata(bcx, name, binding_info);
     }
     bcx
 }
@@ -1114,8 +1126,8 @@ fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
         None => {
             let data = &m[0].data;
-            for &(ref ident, ref value_ptr) in &m[0].bound_ptrs {
-                let binfo = *data.bindings_map.get(ident).unwrap();
+            for &(ref name, ref value_ptr) in &m[0].bound_ptrs {
+                let binfo = *data.bindings_map.get(name).unwrap();
                 call_lifetime_start(bcx, binfo.llmatch);
                 if binfo.trmode == TrByRef && type_is_fat_ptr(bcx.tcx(), binfo.ty) {
                     expr::copy_fat_ptr(bcx, *value_ptr, binfo.llmatch);
@@ -1283,6 +1295,10 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
     let exhaustive = chk.is_infallible() && defaults.is_empty();
     let len = opts.len();
 
+    if exhaustive && kind == Switch {
+        build::Unreachable(else_cx);
+    }
+
     // Compile subtrees for each option
     for (i, opt) in opts.iter().enumerate() {
         // In some cases of range and vector pattern matching, we need to
@@ -1293,7 +1309,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         let mut opt_cx = else_cx;
         let debug_loc = opt.debug_loc();
 
-        if !exhaustive || i + 1 < len {
+        if kind == Switch || !exhaustive || i + 1 < len {
             opt_cx = bcx.fcx.new_temp_block("match_case");
             match kind {
                 Single => Br(bcx, opt_cx.llbb, debug_loc),
@@ -1428,19 +1444,19 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 fn is_discr_reassigned(bcx: Block, discr: &hir::Expr, body: &hir::Expr) -> bool {
     let (vid, field) = match discr.node {
         hir::ExprPath(..) => match bcx.def(discr.id) {
-            def::DefLocal(vid) | def::DefUpvar(vid, _, _) => (vid, None),
+            def::DefLocal(_, vid) | def::DefUpvar(_, vid, _, _) => (vid, None),
             _ => return false
         },
         hir::ExprField(ref base, field) => {
             let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
-                Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _, _)) => vid,
+                Some(def::DefLocal(_, vid)) | Some(def::DefUpvar(_, vid, _, _)) => vid,
                 _ => return false
             };
-            (vid, Some(mc::NamedField(field.node.name)))
+            (vid, Some(mc::NamedField(field.node)))
         },
         hir::ExprTupField(ref base, field) => {
             let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
-                Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _, _)) => vid,
+                Some(def::DefLocal(_, vid)) | Some(def::DefUpvar(_, vid, _, _)) => vid,
                 _ => return false
             };
             (vid, Some(mc::PositionalField(field.node)))
@@ -1509,9 +1525,8 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &hir::Pat,
     let tcx = bcx.tcx();
     let reassigned = is_discr_reassigned(bcx, discr, body);
     let mut bindings_map = FnvHashMap();
-    pat_bindings(&tcx.def_map, &*pat, |bm, p_id, span, path1| {
-        let ident = path1.node;
-        let name = ident.name;
+    pat_bindings_hygienic(&tcx.def_map, &*pat, |bm, p_id, span, path1| {
+        let name = mtwt::resolve(path1.node);
         let variable_ty = node_id_type(bcx, p_id);
         let llvariable_ty = type_of::type_of(ccx, variable_ty);
         let tcx = bcx.tcx();
@@ -1543,7 +1558,7 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &hir::Pat,
                 trmode = TrByRef;
             }
         };
-        bindings_map.insert(ident, BindingInfo {
+        bindings_map.insert(name, BindingInfo {
             llmatch: llmatch,
             trmode: trmode,
             id: p_id,
@@ -1656,7 +1671,7 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         pat_bindings(&tcx.def_map, pat, |_, p_id, _, path1| {
             let scope = cleanup::var_scope(tcx, p_id);
             bcx = mk_binding_alloca(
-                bcx, p_id, path1.node.name, scope, (),
+                bcx, p_id, path1.node, scope, (),
                 "_match::store_local::create_dummy_locals",
                 |(), bcx, Datum { val: llval, ty, kind }| {
                     // Dummy-locals start out uninitialized, so set their
@@ -1693,11 +1708,11 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             //
             // In such cases, the more general path is unsafe, because
             // it assumes it is matching against a valid value.
-            match simple_identifier(&*pat) {
-                Some(ident) => {
+            match simple_name(pat) {
+                Some(name) => {
                     let var_scope = cleanup::var_scope(tcx, local.id);
                     return mk_binding_alloca(
-                        bcx, pat.id, ident.name, var_scope, (),
+                        bcx, pat.id, name, var_scope, (),
                         "_match::store_local",
                         |(), bcx, Datum { val: v, .. }| expr::trans_into(bcx, &**init_expr,
                                                                          expr::SaveIn(v)));
@@ -1872,7 +1887,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let pat_repr = adt::represent_type(bcx.ccx(), pat_ty);
             let pat_v = VariantInfo::of_node(tcx, pat_ty, pat.id);
             for f in fields {
-                let name = f.node.ident.name;
+                let name = f.node.name;
                 let fldptr = adt::trans_field_ptr(
                     bcx,
                     &*pat_repr,
index 9b630037fe8264df5f0616d478f8c30a8175091c..de09e33ec142786b0f6442281c8b5a0e00ac65ea 100644 (file)
@@ -51,9 +51,8 @@ use middle::subst;
 use middle::ty::{self, Ty};
 use middle::ty::Disr;
 use syntax::ast;
-use rustc_front::attr;
-use rustc_front::attr::IntType;
-use rustc_front::hir;
+use syntax::attr;
+use syntax::attr::IntType;
 use trans::_match;
 use trans::build::*;
 use trans::cleanup;
@@ -387,11 +386,11 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let ity = if use_align {
                 // Use the overall alignment
                 match align {
-                    1 => attr::UnsignedInt(hir::TyU8),
-                    2 => attr::UnsignedInt(hir::TyU16),
-                    4 => attr::UnsignedInt(hir::TyU32),
+                    1 => attr::UnsignedInt(ast::TyU8),
+                    2 => attr::UnsignedInt(ast::TyU16),
+                    4 => attr::UnsignedInt(ast::TyU32),
                     8 if machine::llalign_of_min(cx, Type::i64(cx)) == 8 =>
-                        attr::UnsignedInt(hir::TyU64),
+                        attr::UnsignedInt(ast::TyU64),
                     _ => min_ity // use min_ity as a fallback
                 }
             } else {
@@ -583,12 +582,12 @@ fn range_to_inttype(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> IntTyp
     // Lists of sizes to try.  u64 is always allowed as a fallback.
     #[allow(non_upper_case_globals)]
     const choose_shortest: &'static [IntType] = &[
-        attr::UnsignedInt(hir::TyU8), attr::SignedInt(hir::TyI8),
-        attr::UnsignedInt(hir::TyU16), attr::SignedInt(hir::TyI16),
-        attr::UnsignedInt(hir::TyU32), attr::SignedInt(hir::TyI32)];
+        attr::UnsignedInt(ast::TyU8), attr::SignedInt(ast::TyI8),
+        attr::UnsignedInt(ast::TyU16), attr::SignedInt(ast::TyI16),
+        attr::UnsignedInt(ast::TyU32), attr::SignedInt(ast::TyI32)];
     #[allow(non_upper_case_globals)]
     const at_least_32: &'static [IntType] = &[
-        attr::UnsignedInt(hir::TyU32), attr::SignedInt(hir::TyI32)];
+        attr::UnsignedInt(ast::TyU32), attr::SignedInt(ast::TyI32)];
 
     let attempts;
     match hint {
@@ -622,7 +621,7 @@ fn range_to_inttype(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> IntTyp
             return ity;
         }
     }
-    return attr::UnsignedInt(hir::TyU64);
+    return attr::UnsignedInt(ast::TyU64);
 }
 
 pub fn ll_inttype(cx: &CrateContext, ity: IntType) -> Type {
index 891baca75a860f519aabe852679b926998a5b00c..c59237e307849a30c701c0c229314f4b1fb30cde 100644 (file)
@@ -22,6 +22,7 @@ use trans::type_::Type;
 
 use rustc_front::hir as ast;
 use std::ffi::CString;
+use syntax::ast::AsmDialect;
 use libc::{c_uint, c_char};
 
 // Take an inline assembly expression and splat it out via LLVM
@@ -105,8 +106,8 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
     };
 
     let dialect = match ia.dialect {
-        ast::AsmAtt   => llvm::AD_ATT,
-        ast::AsmIntel => llvm::AD_Intel
+        AsmDialect::Att   => llvm::AD_ATT,
+        AsmDialect::Intel => llvm::AD_Intel
     };
 
     let asm = CString::new(ia.asm.as_bytes()).unwrap();
index c77cb49144818b4e94c3d3b3f896b503e0eb30ff..af4c2205e659b8067b981c67ff040b01b5921622 100644 (file)
@@ -15,8 +15,9 @@ use middle::ty;
 use middle::infer;
 use session::config::NoDebugInfo;
 use syntax::abi;
+pub use syntax::attr::InlineAttr;
+use syntax::ast;
 use rustc_front::hir;
-pub use rustc_front::attr::InlineAttr;
 use trans::base;
 use trans::common;
 use trans::context::CrateContext;
@@ -90,8 +91,8 @@ pub fn set_optimize_for_size(val: ValueRef, optimize: bool) {
 
 /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute])
 /// attributes.
-pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[hir::Attribute], llfn: ValueRef) {
-    use rustc_front::attr::*;
+pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) {
+    use syntax::attr::*;
     inline(llfn, find_inline_attr(Some(ccx.sess().diagnostic()), attrs));
 
     // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a
index 79484ad3ddd564d390d92f9524dab72a7c824ba2..14fea610fcf92b202aab2c972f96e7c3c6a9a9cc 100644 (file)
@@ -37,10 +37,10 @@ use llvm;
 use metadata::{csearch, encoder, loader};
 use middle::astencode;
 use middle::cfg;
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::DefId;
 use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
 use middle::weak_lang_items;
-use middle::pat_util::simple_identifier;
+use middle::pat_util::simple_name;
 use middle::subst::Substs;
 use middle::ty::{self, Ty, HasTypeFlags};
 use rustc::front::map as hir_map;
@@ -89,15 +89,14 @@ use libc::c_uint;
 use std::ffi::{CStr, CString};
 use std::cell::{Cell, RefCell};
 use std::collections::{HashMap, HashSet};
-use std::mem;
 use std::str;
 use std::{i8, i16, i32, i64};
 use syntax::abi::{Rust, RustCall, RustIntrinsic, PlatformIntrinsic, Abi};
 use syntax::codemap::Span;
 use syntax::parse::token::InternedString;
+use syntax::attr::AttrMetaMethods;
+use syntax::attr;
 use rustc_front;
-use rustc_front::attr::AttrMetaMethods;
-use rustc_front::attr;
 use rustc_front::visit::Visitor;
 use rustc_front::visit;
 use rustc_front::hir;
@@ -581,12 +580,12 @@ pub fn llty_and_min_for_signed_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
         ty::TyInt(t) => {
             let llty = Type::int_from_ty(cx.ccx(), t);
             let min = match t {
-                hir::TyIs if llty == Type::i32(cx.ccx()) => i32::MIN as u64,
-                hir::TyIs => i64::MIN as u64,
-                hir::TyI8 => i8::MIN as u64,
-                hir::TyI16 => i16::MIN as u64,
-                hir::TyI32 => i32::MIN as u64,
-                hir::TyI64 => i64::MIN as u64,
+                ast::TyIs if llty == Type::i32(cx.ccx()) => i32::MIN as u64,
+                ast::TyIs => i64::MIN as u64,
+                ast::TyI8 => i8::MIN as u64,
+                ast::TyI16 => i16::MIN as u64,
+                ast::TyI32 => i32::MIN as u64,
+                ast::TyI64 => i64::MIN as u64,
             };
             (llty, min)
         }
@@ -1167,7 +1166,7 @@ fn has_nested_returns(tcx: &ty::ctxt, cfg: &cfg::CFG, blk_id: ast::NodeId) -> bo
             }
             Some(hir_map::NodeBlock(blk)) if blk.id == blk_id => {
                 let mut visitor = FindNestedReturn::new();
-                visit::walk_expr_opt(&mut visitor, &blk.expr);
+                walk_list!(&mut visitor, visit_expr, &blk.expr);
                 if visitor.found {
                     return true;
                 }
@@ -1286,7 +1285,7 @@ pub fn init_function<'a, 'tcx>(fcx: &'a FunctionContext<'a, 'tcx>,
 
     // Create the drop-flag hints for every unfragmented path in the function.
     let tcx = fcx.ccx.tcx();
-    let fn_did = DefId { krate: LOCAL_CRATE, node: fcx.id };
+    let fn_did = tcx.map.local_def_id(fcx.id);
     let mut hints = fcx.lldropflag_hints.borrow_mut();
     let fragment_infos = tcx.fragment_infos.borrow();
 
@@ -1447,10 +1446,10 @@ pub fn create_datums_for_fn_args<'a, 'tcx>(mut bcx: Block<'a, 'tcx>,
         };
 
         let pat = &*args[i].pat;
-        bcx = if let Some(ident) = simple_identifier(&*pat) {
+        bcx = if let Some(name) = simple_name(pat) {
             // Generate nicer LLVM for the common case of fn a pattern
             // like `x: T`
-            set_value_name(arg_datum.val, &bcx.name(ident.name));
+            set_value_name(arg_datum.val, &bcx.name(name));
             bcx.fcx.lllocals.borrow_mut().insert(pat.id, arg_datum);
             bcx
         } else {
@@ -1563,7 +1562,7 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                    llfndecl: ValueRef,
                                    param_substs: &'tcx Substs<'tcx>,
                                    fn_ast_id: ast::NodeId,
-                                   _attributes: &[hir::Attribute],
+                                   _attributes: &[ast::Attribute],
                                    output_type: ty::FnOutput<'tcx>,
                                    abi: Abi,
                                    closure_env: closure::ClosureEnv<'b>) {
@@ -1576,7 +1575,7 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
            param_substs);
 
     let has_env = match closure_env {
-        closure::ClosureEnv::Closure(_) => true,
+        closure::ClosureEnv::Closure(..) => true,
         closure::ClosureEnv::NotClosure => false,
     };
 
@@ -1682,7 +1681,7 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                           llfndecl: ValueRef,
                           param_substs: &'tcx Substs<'tcx>,
                           id: ast::NodeId,
-                          attrs: &[hir::Attribute]) {
+                          attrs: &[ast::Attribute]) {
     let _s = StatRecorder::new(ccx, ccx.tcx().map.path_to_string(id).to_string());
     debug!("trans_fn(param_substs={:?})", param_substs);
     let _icx = push_ctxt("trans_fn");
@@ -2085,7 +2084,8 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) {
                     // error in trans. This is used to write compile-fail tests
                     // that actually test that compilation succeeds without
                     // reporting an error.
-                    if ccx.tcx().has_attr(DefId::local(item.id), "rustc_error") {
+                    let item_def_id = ccx.tcx().map.local_def_id(item.id);
+                    if ccx.tcx().has_attr(item_def_id, "rustc_error") {
                         ccx.tcx().sess.span_fatal(item.span, "compilation successful");
                     }
                 }
@@ -2099,7 +2099,7 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) {
       }
       hir::ItemImpl(_, _, ref generics, _, _, ref impl_items) => {
         meth::trans_impl(ccx,
-                         item.ident,
+                         item.name,
                          &impl_items[..],
                          generics,
                          item.id);
@@ -2124,7 +2124,10 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) {
           let mut v = TransItemVisitor{ ccx: ccx };
           v.visit_expr(&**expr);
 
-          let g = consts::trans_static(ccx, m, expr, item.id, &item.attrs);
+          let g = match consts::trans_static(ccx, m, expr, item.id, &item.attrs) {
+              Ok(g) => g,
+              Err(err) => ccx.tcx().sess.span_fatal(expr.span, &err.description()),
+          };
           set_global_section(ccx, g, item);
           update_linkage(ccx, g, Some(item.id), OriginalTranslation);
       },
@@ -2252,13 +2255,14 @@ pub fn create_entry_wrapper(ccx: &CrateContext,
                     Ok(id) => id,
                     Err(s) => { ccx.sess().fatal(&s[..]); }
                 };
-                let start_fn = if start_def_id.is_local() {
-                    get_item_val(ccx, start_def_id.node)
-                } else {
-                    let start_fn_type = csearch::get_type(ccx.tcx(),
-                                                          start_def_id).ty;
-                    trans_external_path(ccx, start_def_id, start_fn_type)
-                };
+                let start_fn =
+                    if let Some(start_node_id) = ccx.tcx().map.as_local_node_id(start_def_id) {
+                        get_item_val(ccx, start_node_id)
+                    } else {
+                        let start_fn_type = csearch::get_type(ccx.tcx(),
+                                                              start_def_id).ty;
+                        trans_external_path(ccx, start_def_id, start_fn_type)
+                    };
 
                 let args = {
                     let opaque_rust_main = llvm::LLVMBuildPointerCast(bld,
@@ -2294,7 +2298,7 @@ pub fn create_entry_wrapper(ccx: &CrateContext,
 }
 
 fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, id: ast::NodeId,
-                           ty: Ty<'tcx>, attrs: &[hir::Attribute]) -> String {
+                           ty: Ty<'tcx>, attrs: &[ast::Attribute]) -> String {
     match ccx.external_srcs().borrow().get(&id) {
         Some(&did) => {
             let sym = csearch::get_symbol(&ccx.sess().cstore, did);
@@ -2307,10 +2311,11 @@ fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, id: ast::NodeId,
     match attr::find_export_name_attr(ccx.sess().diagnostic(), attrs) {
         // Use provided name
         Some(name) => name.to_string(),
-        _ => ccx.tcx().map.with_path(id, |path| {
+        _ => {
+            let path = ccx.tcx().map.def_path_from_id(id);
             if attr::contains_name(attrs, "no_mangle") {
                 // Don't mangle
-                path.last().unwrap().to_string()
+                path.last().unwrap().data.to_string()
             } else {
                 match weak_lang_items::link_name(attrs) {
                     Some(name) => name.to_string(),
@@ -2320,7 +2325,7 @@ fn exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, id: ast::NodeId,
                     }
                 }
             }
-        })
+        }
     }
 }
 
@@ -2425,13 +2430,12 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
 
         hir_map::NodeVariant(ref v) => {
             let llfn;
-            let args = match v.node.kind {
-                hir::TupleVariantKind(ref args) => args,
-                hir::StructVariantKind(_) => {
-                    ccx.sess().bug("struct variant kind unexpected in get_item_val")
-                }
+            let fields = if v.node.data.is_struct() {
+                ccx.sess().bug("struct variant kind unexpected in get_item_val")
+            } else {
+                v.node.data.fields()
             };
-            assert!(!args.is_empty());
+            assert!(!fields.is_empty());
             let ty = ccx.tcx().node_id_to_type(id);
             let parent = ccx.tcx().map.get_parent(id);
             let enm = ccx.tcx().map.expect_item(parent);
@@ -2452,12 +2456,11 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
 
         hir_map::NodeStructCtor(struct_def) => {
             // Only register the constructor if this is a tuple-like struct.
-            let ctor_id = match struct_def.ctor_id {
-                None => {
-                    ccx.sess().bug("attempt to register a constructor of \
-                                    a non-tuple-like struct")
-                }
-                Some(ctor_id) => ctor_id,
+            let ctor_id = if struct_def.is_struct() {
+                ccx.sess().bug("attempt to register a constructor of \
+                                  a non-tuple-like struct")
+            } else {
+                struct_def.id()
             };
             let parent = ccx.tcx().map.get_parent(id);
             let struct_item = ccx.tcx().map.expect_item(parent);
@@ -2492,7 +2495,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
 }
 
 fn register_method(ccx: &CrateContext, id: ast::NodeId,
-                   attrs: &[hir::Attribute], span: Span) -> ValueRef {
+                   attrs: &[ast::Attribute], span: Span) -> ValueRef {
     let mty = ccx.tcx().node_id_to_type(id);
 
     let sym = exported_name(ccx, id, mty, &attrs);
@@ -2660,11 +2663,7 @@ impl Iterator for ValueIter {
     fn next(&mut self) -> Option<ValueRef> {
         let old = self.cur;
         if !old.is_null() {
-            self.cur = unsafe {
-                let step: unsafe extern "C" fn(ValueRef) -> ValueRef =
-                    mem::transmute_copy(&self.step);
-                step(old)
-            };
+            self.cur = unsafe { (self.step)(old) };
             Some(old)
         } else {
             None
index fa3824866ccb8880738d9055fa54e1e9fe94437a..00d8fdad32de1814e9e7612b4d7651fe51b9e112 100644 (file)
@@ -410,18 +410,53 @@ pub fn compute_abi_info(ccx: &CrateContext,
         }
     }
 
-    let mut arg_tys = Vec::new();
-    for t in atys {
-        let ty = x86_64_ty(ccx, *t, |cls| cls.is_pass_byval(), Attribute::ByVal);
-        arg_tys.push(ty);
-    }
+    let mut int_regs = 6; // RDI, RSI, RDX, RCX, R8, R9
+    let mut sse_regs = 8; // XMM0-7
 
     let ret_ty = if ret_def {
-        x86_64_ty(ccx, rty, |cls| cls.is_ret_bysret(), Attribute::StructRet)
+        x86_64_ty(ccx, rty, |cls| {
+            if cls.is_ret_bysret() {
+                // `sret` parameter thus one less register available
+                int_regs -= 1;
+                true
+            } else {
+                false
+            }
+        }, Attribute::StructRet)
     } else {
         ArgType::direct(Type::void(ccx), None, None, None)
     };
 
+    let mut arg_tys = Vec::new();
+    for t in atys {
+        let ty = x86_64_ty(ccx, *t, |cls| {
+            let needed_int = cls.iter().filter(|&&c| c == Int).count() as isize;
+            let needed_sse = cls.iter().filter(|c| c.is_sse()).count() as isize;
+            let in_mem = cls.is_pass_byval() ||
+                         int_regs < needed_int ||
+                         sse_regs < needed_sse;
+            if in_mem {
+                // `byval` parameter thus one less integer register available
+                int_regs -= 1;
+            } else {
+                // split into sized chunks passed individually
+                int_regs -= needed_int;
+                sse_regs -= needed_sse;
+            }
+            in_mem
+        }, Attribute::ByVal);
+        arg_tys.push(ty);
+
+        // An integer, pointer, double or float parameter
+        // thus the above closure passed to `x86_64_ty` won't
+        // get called.
+        if t.kind() == Integer || t.kind() == Pointer {
+            int_regs -= 1;
+        } else if t.kind() == Double || t.kind() == Float {
+            sse_regs -= 1;
+        }
+    }
+
     return FnType {
         arg_tys: arg_tys,
         ret_ty: ret_ty,
index 0a39150dbd36a684fcdd358588044a6d841d73d1..120c8dc0384cef59da2c947aa50b500cc866f46a 100644 (file)
@@ -46,7 +46,7 @@ pub fn compute_abi_info(ccx: &CrateContext,
                     2 => ArgType::direct(t, Some(Type::i16(ccx)), None, None),
                     4 => ArgType::direct(t, Some(Type::i32(ccx)), None, None),
                     8 => ArgType::direct(t, Some(Type::i64(ccx)), None, None),
-                    _ => ArgType::indirect(t, Some(Attribute::ByVal))
+                    _ => ArgType::indirect(t, None)
                 }
             }
             _ => {
index 124f50d660329bddae84f400fbc1a18a0b458fae..c8525e33e2667e6f22619c784cf422f97dd97ace 100644 (file)
@@ -22,11 +22,12 @@ use arena::TypedArena;
 use back::link;
 use session;
 use llvm::{self, ValueRef, get_params};
+use metadata::cstore::LOCAL_CRATE;
 use middle::def;
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::DefId;
 use middle::infer::normalize_associated_type;
 use middle::subst;
-use middle::subst::{Subst, Substs};
+use middle::subst::{Substs};
 use rustc::front::map as hir_map;
 use trans::adt;
 use trans::base;
@@ -139,8 +140,10 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &hir::Expr)
         match def {
             def::DefFn(did, _) if {
                 let maybe_def_id = inline::get_local_instance(bcx.ccx(), did);
-                let maybe_ast_node = maybe_def_id.and_then(|def_id| bcx.tcx().map
-                                                                             .find(def_id.node));
+                let maybe_ast_node = maybe_def_id.and_then(|def_id| {
+                    let node_id = bcx.tcx().map.as_local_node_id(def_id).unwrap();
+                    bcx.tcx().map.find(node_id)
+                });
                 match maybe_ast_node {
                     Some(hir_map::NodeStructCtor(_)) => true,
                     _ => false
@@ -161,7 +164,8 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &hir::Expr)
                                                     ExprId(ref_expr.id),
                                                     bcx.fcx.param_substs);
                 let def_id = inline::maybe_instantiate_inline(bcx.ccx(), did);
-                Callee { bcx: bcx, data: Intrinsic(def_id.node, substs), ty: expr_ty }
+                let node_id = bcx.tcx().map.as_local_node_id(def_id).unwrap();
+                Callee { bcx: bcx, data: Intrinsic(node_id, substs), ty: expr_ty }
             }
             def::DefFn(did, _) => {
                 fn_callee(bcx, trans_fn_ref(bcx.ccx(), did, ExprId(ref_expr.id),
@@ -211,8 +215,8 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &hir::Expr)
             }
             def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) |
             def::DefTy(..) | def::DefPrimTy(..) | def::DefAssociatedTy(..) |
-            def::DefUse(..) | def::DefRegion(..) | def::DefLabel(..) |
-            def::DefTyParam(..) | def::DefSelfTy(..) => {
+            def::DefUse(..) | def::DefLabel(..) | def::DefTyParam(..) |
+            def::DefSelfTy(..) => {
                 bcx.tcx().sess.span_bug(
                     ref_expr.span,
                     &format!("cannot translate def {:?} \
@@ -335,7 +339,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
     let llargs = get_params(fcx.llfn);
 
     let self_idx = fcx.arg_offset();
-    // the first argument (`self`) will be ptr to the the fn pointer
+    // the first argument (`self`) will be ptr to the fn pointer
     let llfnpointer = if is_by_ref {
         Load(bcx, llargs[self_idx])
     } else {
@@ -398,91 +402,30 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
     assert!(!substs.types.has_escaping_regions());
     let substs = substs.erase_regions();
 
-    // Load the info for the appropriate trait if necessary.
-    match tcx.trait_of_item(def_id) {
-        None => {}
-        Some(trait_id) => {
-            tcx.populate_implementations_for_trait_if_necessary(trait_id)
-        }
-    }
-
-    // We need to do a bunch of special handling for default methods.
-    // We need to modify the def_id and our substs in order to monomorphize
-    // the function.
-    let (is_default, def_id, substs) = match tcx.provided_source(def_id) {
-        None => {
-            (false, def_id, tcx.mk_substs(substs))
-        }
-        Some(source_id) => {
-            // There are two relevant substitutions when compiling
-            // default methods. First, there is the substitution for
-            // the type parameters of the impl we are using and the
-            // method we are calling. This substitution is the substs
-            // argument we already have.
-            // In order to compile a default method, though, we need
-            // to consider another substitution: the substitution for
-            // the type parameters on trait; the impl we are using
-            // implements the trait at some particular type
-            // parameters, and we need to substitute for those first.
-            // So, what we need to do is find this substitution and
-            // compose it with the one we already have.
-
-            let impl_id = tcx.impl_or_trait_item(def_id).container()
-                                                             .id();
-            let impl_or_trait_item = tcx.impl_or_trait_item(source_id);
-            match impl_or_trait_item {
-                ty::MethodTraitItem(method) => {
-                    let trait_ref = tcx.impl_trait_ref(impl_id).unwrap();
-
-                    // Compute the first substitution
-                    let first_subst =
-                        tcx.make_substs_for_receiver_types(&trait_ref, &*method)
-                        .erase_regions();
-
-                    // And compose them
-                    let new_substs = tcx.mk_substs(first_subst.subst(tcx, &substs));
-
-                    debug!("trans_fn_with_vtables - default method: \
-                            substs = {:?}, trait_subst = {:?}, \
-                            first_subst = {:?}, new_subst = {:?}",
-                           substs, trait_ref.substs,
-                           first_subst, new_substs);
-
-                    (true, source_id, new_substs)
-                }
-                _ => {
-                    tcx.sess.bug("trans_fn_ref_with_vtables() tried \
-                                  to translate a non-method?!")
-                }
-            }
-        }
-    };
-
     // Check whether this fn has an inlined copy and, if so, redirect
     // def_id to the local id of the inlined copy.
     let def_id = inline::maybe_instantiate_inline(ccx, def_id);
 
-    // We must monomorphise if the fn has type parameters, is a default method,
-    // or is a named tuple constructor.
-    let must_monomorphise = if !substs.types.is_empty() || is_default {
-        true
-    } else if def_id.is_local() {
+    fn is_named_tuple_constructor(tcx: &ty::ctxt, def_id: DefId) -> bool {
+        let node_id = match tcx.map.as_local_node_id(def_id) {
+            Some(n) => n,
+            None => { return false; }
+        };
         let map_node = session::expect(
-            ccx.sess(),
-            tcx.map.find(def_id.node),
+            &tcx.sess,
+            tcx.map.find(node_id),
             || "local item should be in ast map".to_string());
 
         match map_node {
-            hir_map::NodeVariant(v) => match v.node.kind {
-                hir::TupleVariantKind(ref args) => !args.is_empty(),
-                _ => false
-            },
+            hir_map::NodeVariant(v) => {
+                v.node.data.is_tuple()
+            }
             hir_map::NodeStructCtor(_) => true,
             _ => false
         }
-    } else {
-        false
-    };
+    }
+    let must_monomorphise =
+        !substs.types.is_empty() || is_named_tuple_constructor(tcx, def_id);
 
     debug!("trans_fn_ref_with_substs({:?}) must_monomorphise: {}",
            def_id, must_monomorphise);
@@ -497,6 +440,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
             MethodCallKey(_) => None,
         };
 
+        let substs = tcx.mk_substs(substs);
         let (val, fn_ty, must_cast) =
             monomorphize::monomorphic_fn(ccx, def_id, substs, opt_ref_id);
         if must_cast && node != ExprId(0) {
@@ -526,9 +470,9 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
 
     // Find the actual function pointer.
     let mut val = {
-        if def_id.is_local() {
+        if let Some(node_id) = ccx.tcx().map.as_local_node_id(def_id) {
             // Internal reference.
-            get_item_val(ccx, def_id.node)
+            get_item_val(ccx, node_id)
         } else {
             // External reference.
             trans_external_path(ccx, def_id, fn_type)
@@ -561,10 +505,10 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
     let llty = type_of::type_of_fn_from_ty(ccx, fn_type);
     let llptrty = llty.ptr_to();
     if common::val_ty(val) != llptrty {
-        debug!("trans_fn_ref_with_vtables(): casting pointer!");
+        debug!("trans_fn_ref_with_substs(): casting pointer!");
         val = consts::ptrcast(val, llptrty);
     } else {
-        debug!("trans_fn_ref_with_vtables(): not casting pointer!");
+        debug!("trans_fn_ref_with_substs(): not casting pointer!");
     }
 
     Datum::new(val, fn_type, Rvalue::new(ByValue))
index dc9ea62e9d11aedfd520cfb6e5b487b44e55cde8..d3509c2f8133a259be40e758e01bc6b2ef0f8284 100644 (file)
@@ -36,6 +36,7 @@ use rustc_front::hir;
 
 
 fn load_closure_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                        closure_def_id: DefId,
                                         arg_scope_id: ScopeId,
                                         freevars: &[ty::Freevar])
                                         -> Block<'blk, 'tcx>
@@ -43,10 +44,9 @@ fn load_closure_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let _icx = push_ctxt("closure::load_closure_environment");
 
     // Special case for small by-value selfs.
-    let closure_id = DefId::local(bcx.fcx.id);
-    let self_type = self_type_for_closure(bcx.ccx(), closure_id,
-                                                  node_id_type(bcx, closure_id.node));
-    let kind = kind_for_closure(bcx.ccx(), closure_id);
+    let closure_ty = node_id_type(bcx, bcx.fcx.id);
+    let self_type = self_type_for_closure(bcx.ccx(), closure_def_id, closure_ty);
+    let kind = kind_for_closure(bcx.ccx(), closure_def_id);
     let llenv = if kind == ty::FnOnceClosureKind &&
             !arg_is_indirect(bcx.ccx(), self_type) {
         let datum = rvalue_scratch_datum(bcx,
@@ -69,8 +69,8 @@ fn load_closure_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     };
 
     for (i, freevar) in freevars.iter().enumerate() {
-        let upvar_id = ty::UpvarId { var_id: freevar.def.local_node_id(),
-                                     closure_expr_id: closure_id.node };
+        let upvar_id = ty::UpvarId { var_id: freevar.def.var_id(),
+                                     closure_expr_id: bcx.fcx.id };
         let upvar_capture = bcx.tcx().upvar_capture(upvar_id).unwrap();
         let mut upvar_ptr = StructGEP(bcx, llenv, i);
         let captured_by_ref = match upvar_capture {
@@ -80,21 +80,21 @@ fn load_closure_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 true
             }
         };
-        let def_id = freevar.def.def_id();
-        bcx.fcx.llupvars.borrow_mut().insert(def_id.node, upvar_ptr);
+        let node_id = freevar.def.var_id();
+        bcx.fcx.llupvars.borrow_mut().insert(node_id, upvar_ptr);
 
         if kind == ty::FnOnceClosureKind && !captured_by_ref {
             let hint = bcx.fcx.lldropflag_hints.borrow().hint_datum(upvar_id.var_id);
             bcx.fcx.schedule_drop_mem(arg_scope_id,
                                       upvar_ptr,
-                                      node_id_type(bcx, def_id.node),
+                                      node_id_type(bcx, node_id),
                                       hint)
         }
 
         if let Some(env_pointer_alloca) = env_pointer_alloca {
             debuginfo::create_captured_var_metadata(
                 bcx,
-                def_id.node,
+                node_id,
                 env_pointer_alloca,
                 i,
                 captured_by_ref,
@@ -107,7 +107,7 @@ fn load_closure_environment<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
 pub enum ClosureEnv<'a> {
     NotClosure,
-    Closure(&'a [ty::Freevar]),
+    Closure(DefId, &'a [ty::Freevar]),
 }
 
 impl<'a> ClosureEnv<'a> {
@@ -116,11 +116,11 @@ impl<'a> ClosureEnv<'a> {
     {
         match self {
             ClosureEnv::NotClosure => bcx,
-            ClosureEnv::Closure(freevars) => {
+            ClosureEnv::Closure(def_id, freevars) => {
                 if freevars.is_empty() {
                     bcx
                 } else {
-                    load_closure_environment(bcx, arg_scope, freevars)
+                    load_closure_environment(bcx, def_id, arg_scope, freevars)
                 }
             }
         }
@@ -147,9 +147,8 @@ pub fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         return llfn;
     }
 
-    let symbol = ccx.tcx().map.with_path(closure_id.node, |path| {
-        mangle_internal_name_by_path_and_seq(path, "closure")
-    });
+    let path = ccx.tcx().def_path(closure_id);
+    let symbol = mangle_internal_name_by_path_and_seq(path, "closure");
 
     let function_type = ccx.tcx().mk_closure_from_closure_substs(closure_id, Box::new(substs));
     let llfn = declare::define_internal_rust_fn(ccx, &symbol[..], function_type);
@@ -176,9 +175,14 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
                                     decl: &hir::FnDecl,
                                     body: &hir::Block,
                                     id: ast::NodeId,
+                                    closure_def_id: DefId, // (*)
                                     closure_substs: &'tcx ty::ClosureSubsts<'tcx>)
                                     -> Option<Block<'a, 'tcx>>
 {
+    // (*) Note that in the case of inlined functions, the `closure_def_id` will be the
+    // defid of the closure in its original crate, whereas `id` will be the id of the local
+    // inlined copy.
+
     let param_substs = closure_substs.func_substs;
 
     let ccx = match dest {
@@ -188,10 +192,10 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
     let tcx = ccx.tcx();
     let _icx = push_ctxt("closure::trans_closure_expr");
 
-    debug!("trans_closure_expr()");
+    debug!("trans_closure_expr(id={:?}, closure_def_id={:?}, closure_substs={:?})",
+           id, closure_def_id, closure_substs);
 
-    let closure_id = DefId::local(id);
-    let llfn = get_or_create_closure_declaration(ccx, closure_id, closure_substs);
+    let llfn = get_or_create_closure_declaration(ccx, closure_def_id, closure_substs);
 
     // Get the type of this closure. Use the current `param_substs` as
     // the closure substitutions. This makes sense because the closure
@@ -200,7 +204,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
     // of the closure expression.
 
     let infcx = infer::normalizing_infer_ctxt(ccx.tcx(), &ccx.tcx().tables);
-    let function_type = infcx.closure_type(closure_id, closure_substs);
+    let function_type = infcx.closure_type(closure_def_id, closure_substs);
 
     let freevars: Vec<ty::Freevar> =
         tcx.with_freevars(id, |fv| fv.iter().cloned().collect());
@@ -216,7 +220,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
                   &[],
                   sig.output,
                   function_type.abi,
-                  ClosureEnv::Closure(&freevars));
+                  ClosureEnv::Closure(closure_def_id, &freevars));
 
     // Don't hoist this to the top of the function. It's perfectly legitimate
     // to have a zero-size closure (in which case dest will be `Ignore`) and
@@ -235,7 +239,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
     for (i, freevar) in freevars.iter().enumerate() {
         let datum = expr::trans_local_var(bcx, freevar.def);
         let upvar_slot_dest = adt::trans_field_ptr(bcx, &*repr, dest_addr, 0, i);
-        let upvar_id = ty::UpvarId { var_id: freevar.def.local_node_id(),
+        let upvar_id = ty::UpvarId { var_id: freevar.def.var_id(),
                                      closure_expr_id: id };
         match tcx.upvar_capture(upvar_id).unwrap() {
             ty::UpvarCapture::ByValue => {
index ec34d0dd5925782f23ce2a8a47ebf37dadc84346..d160465c619b95e80f6c2e907b6e33c987d87fe0 100644 (file)
@@ -39,7 +39,6 @@ use trans::type_of;
 use middle::traits;
 use middle::ty::{self, HasTypeFlags, Ty};
 use middle::ty::fold::{TypeFolder, TypeFoldable};
-use rustc::front::map::{PathElem, PathName};
 use rustc_front::hir;
 use util::nodemap::{FnvHashMap, NodeMap};
 
@@ -167,11 +166,11 @@ pub fn return_type_is_void(ccx: &CrateContext, ty: Ty) -> bool {
 
 /// Generates a unique symbol based off the name given. This is used to create
 /// unique symbols for things like closures.
-pub fn gensym_name(name: &str) -> PathElem {
-    let num = token::gensym(name).usize();
+pub fn gensym_name(name: &str) -> ast::Name {
+    let num = token::gensym(name).0;
     // use one colon which will get translated to a period by the mangler, and
     // we're guaranteed that `num` is globally unique for this crate.
-    PathName(token::gensym(&format!("{}:{}", name, num)))
+    token::gensym(&format!("{}:{}", name, num))
 }
 
 /*
@@ -829,7 +828,7 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va
                                                 !null_terminated as Bool);
 
         let gsym = token::gensym("str");
-        let sym = format!("str{}", gsym.usize());
+        let sym = format!("str{}", gsym.0);
         let g = declare::define_global(cx, &sym[..], val_ty(sc)).unwrap_or_else(||{
             cx.sess().bug(&format!("symbol `{}` is already defined", sym));
         });
@@ -1020,7 +1019,7 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                    trait_ref);
             ccx.sess().span_fatal(
                 span,
-                "reached the recursion limit during monomorphization");
+                "reached the recursion limit during monomorphization (selection ambiguity)");
         }
         Err(e) => {
             tcx.sess.span_bug(
@@ -1145,8 +1144,9 @@ pub fn inlined_variant_def<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         }), ..}) => ty,
         _ => ctor_ty
     }.ty_adt_def().unwrap();
+    let inlined_vid_def_id = ccx.tcx().map.local_def_id(inlined_vid);
     adt_def.variants.iter().find(|v| {
-        DefId::local(inlined_vid) == v.did ||
+        inlined_vid_def_id == v.did ||
             ccx.external().borrow().get(&v.did) == Some(&Some(inlined_vid))
     }).unwrap_or_else(|| {
         ccx.sess().bug(&format!("no variant for {:?}::{}", adt_def, inlined_vid))
index a2d74635b5e1ce6f2a54ae350fde781565392256..90faef51c2c6c6a3444d2afd3ae3dbf173ef4cb8 100644 (file)
@@ -13,8 +13,9 @@ use back::abi;
 use llvm;
 use llvm::{ConstFCmp, ConstICmp, SetLinkage, SetUnnamedAddr};
 use llvm::{InternalLinkage, ValueRef, Bool, True};
+use metadata::cstore::LOCAL_CRATE;
 use middle::{check_const, def};
-use middle::const_eval::{self, ConstVal};
+use middle::const_eval::{self, ConstVal, ConstEvalErr};
 use middle::const_eval::{const_int_checked_neg, const_uint_checked_neg};
 use middle::const_eval::{const_int_checked_add, const_uint_checked_add};
 use middle::const_eval::{const_int_checked_sub, const_uint_checked_sub};
@@ -25,10 +26,13 @@ use middle::const_eval::{const_int_checked_shl, const_uint_checked_shl};
 use middle::const_eval::{const_int_checked_shr, const_uint_checked_shr};
 use middle::const_eval::EvalHint::ExprTypeChecked;
 use middle::const_eval::eval_const_expr_partial;
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::DefId;
 use trans::{adt, closure, debuginfo, expr, inline, machine};
 use trans::base::{self, push_ctxt};
-use trans::common::*;
+use trans::common::{CrateContext, C_integral, C_floating, C_bool, C_str_slice, C_bytes, val_ty};
+use trans::common::{type_is_sized, ExprOrMethodCall, node_id_substs, C_nil, const_get_elt};
+use trans::common::{C_struct, C_undef, const_to_opt_int, const_to_opt_uint, VariantInfo, C_uint};
+use trans::common::{type_is_fat_ptr, Field, C_vector, C_array, C_null, ExprId, MethodCallKey};
 use trans::declare;
 use trans::monomorphize;
 use trans::type_::Type;
@@ -41,30 +45,31 @@ use middle::ty::cast::{CastTy,IntTy};
 use util::nodemap::NodeMap;
 
 use rustc_front::hir;
-use rustc_front::attr;
 
 use std::ffi::{CStr, CString};
+use std::borrow::Cow;
 use libc::c_uint;
 use syntax::ast;
+use syntax::attr;
 use syntax::parse::token;
 use syntax::ptr::P;
 
 pub type FnArgMap<'a> = Option<&'a NodeMap<ValueRef>>;
 
-pub fn const_lit(cx: &CrateContext, e: &hir::Expr, lit: &hir::Lit)
+pub fn const_lit(cx: &CrateContext, e: &hir::Expr, lit: &ast::Lit)
     -> ValueRef {
     let _icx = push_ctxt("trans_lit");
     debug!("const_lit: {:?}", lit);
     match lit.node {
-        hir::LitByte(b) => C_integral(Type::uint_from_ty(cx, hir::TyU8), b as u64, false),
-        hir::LitChar(i) => C_integral(Type::char(cx), i as u64, false),
-        hir::LitInt(i, hir::SignedIntLit(t, _)) => {
+        ast::LitByte(b) => C_integral(Type::uint_from_ty(cx, ast::TyU8), b as u64, false),
+        ast::LitChar(i) => C_integral(Type::char(cx), i as u64, false),
+        ast::LitInt(i, ast::SignedIntLit(t, _)) => {
             C_integral(Type::int_from_ty(cx, t), i, true)
         }
-        hir::LitInt(u, hir::UnsignedIntLit(t)) => {
+        ast::LitInt(u, ast::UnsignedIntLit(t)) => {
             C_integral(Type::uint_from_ty(cx, t), u, false)
         }
-        hir::LitInt(i, hir::UnsuffixedIntLit(_)) => {
+        ast::LitInt(i, ast::UnsuffixedIntLit(_)) => {
             let lit_int_ty = cx.tcx().node_id_to_type(e.id);
             match lit_int_ty.sty {
                 ty::TyInt(t) => {
@@ -79,10 +84,10 @@ pub fn const_lit(cx: &CrateContext, e: &hir::Expr, lit: &hir::Lit)
                                 lit_int_ty))
             }
         }
-        hir::LitFloat(ref fs, t) => {
+        ast::LitFloat(ref fs, t) => {
             C_floating(&fs, Type::float_from_ty(cx, t))
         }
-        hir::LitFloatUnsuffixed(ref fs) => {
+        ast::LitFloatUnsuffixed(ref fs) => {
             let lit_float_ty = cx.tcx().node_id_to_type(e.id);
             match lit_float_ty.sty {
                 ty::TyFloat(t) => {
@@ -94,10 +99,10 @@ pub fn const_lit(cx: &CrateContext, e: &hir::Expr, lit: &hir::Lit)
                 }
             }
         }
-        hir::LitBool(b) => C_bool(cx, b),
-        hir::LitStr(ref s, _) => C_str_slice(cx, (*s).clone()),
-        hir::LitByteStr(ref data) => {
-            addr_of(cx, C_bytes(cx, &data[..]), "byte_str")
+        ast::LitBool(b) => C_bool(cx, b),
+        ast::LitStr(ref s, _) => C_str_slice(cx, (*s).clone()),
+        ast::LitByteStr(ref data) => {
+            addr_of(cx, C_bytes(cx, &data[..]), 1, "byte_str")
         }
     }
 }
@@ -110,17 +115,19 @@ pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef {
 
 fn addr_of_mut(ccx: &CrateContext,
                cv: ValueRef,
+               align: machine::llalign,
                kind: &str)
                -> ValueRef {
     unsafe {
         // FIXME: this totally needs a better name generation scheme, perhaps a simple global
         // counter? Also most other uses of gensym in trans.
         let gsym = token::gensym("_");
-        let name = format!("{}{}", kind, gsym.usize());
+        let name = format!("{}{}", kind, gsym.0);
         let gv = declare::define_global(ccx, &name[..], val_ty(cv)).unwrap_or_else(||{
             ccx.sess().bug(&format!("symbol `{}` is already defined", name));
         });
         llvm::LLVMSetInitializer(gv, cv);
+        llvm::LLVMSetAlignment(gv, align);
         SetLinkage(gv, InternalLinkage);
         SetUnnamedAddr(gv, true);
         gv
@@ -129,13 +136,23 @@ fn addr_of_mut(ccx: &CrateContext,
 
 pub fn addr_of(ccx: &CrateContext,
                cv: ValueRef,
+               align: machine::llalign,
                kind: &str)
                -> ValueRef {
     match ccx.const_globals().borrow().get(&cv) {
-        Some(&gv) => return gv,
+        Some(&gv) => {
+            unsafe {
+                // Upgrade the alignment in cases where the same constant is used with different
+                // alignment requirements
+                if align > llvm::LLVMGetAlignment(gv) {
+                    llvm::LLVMSetAlignment(gv, align);
+                }
+            }
+            return gv;
+        }
         None => {}
     }
-    let gv = addr_of_mut(ccx, cv, kind);
+    let gv = addr_of_mut(ccx, cv, align, kind);
     unsafe {
         llvm::LLVMSetGlobalConstant(gv, True);
     }
@@ -178,7 +195,8 @@ fn const_fn_call<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                            node: ExprOrMethodCall,
                            def_id: DefId,
                            arg_vals: &[ValueRef],
-                           param_substs: &'tcx Substs<'tcx>) -> ValueRef {
+                           param_substs: &'tcx Substs<'tcx>,
+                           trueconst: TrueConst) -> Result<ValueRef, ConstEvalFailure> {
     let fn_like = const_eval::lookup_const_fn_by_id(ccx.tcx(), def_id);
     let fn_like = fn_like.expect("lookup_const_fn_by_id failed in const_fn_call");
 
@@ -191,9 +209,9 @@ fn const_fn_call<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let substs = ccx.tcx().mk_substs(node_id_substs(ccx, node, param_substs));
     match fn_like.body().expr {
         Some(ref expr) => {
-            const_expr(ccx, &**expr, substs, Some(&fn_args)).0
-        }
-        None => C_nil(ccx)
+            const_expr(ccx, &**expr, substs, Some(&fn_args), trueconst).map(|(res, _)| res)
+        },
+        None => Ok(C_nil(ccx)),
     }
 }
 
@@ -216,19 +234,57 @@ pub fn get_const_expr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     }
 }
 
+pub enum ConstEvalFailure {
+    /// in case the const evaluator failed on something that panic at runtime
+    /// as defined in RFC 1229
+    Runtime(ConstEvalErr),
+    // in case we found a true constant
+    Compiletime(ConstEvalErr),
+}
+
+impl ConstEvalFailure {
+    fn into_inner(self) -> ConstEvalErr {
+        match self {
+            Runtime(e) => e,
+            Compiletime(e) => e,
+        }
+    }
+    pub fn description(&self) -> Cow<str> {
+        match self {
+            &Runtime(ref e) => e.description(),
+            &Compiletime(ref e) => e.description(),
+        }
+    }
+}
+
+#[derive(Copy, Clone)]
+pub enum TrueConst {
+    Yes, No
+}
+
+use self::ConstEvalFailure::*;
+
 fn get_const_val(ccx: &CrateContext,
                  def_id: DefId,
-                 ref_expr: &hir::Expr) -> ValueRef {
+                 ref_expr: &hir::Expr) -> Result<ValueRef, ConstEvalFailure> {
     let expr = get_const_expr(ccx, def_id, ref_expr);
     let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
-    get_const_expr_as_global(ccx, expr, check_const::ConstQualif::empty(), empty_substs)
+    match get_const_expr_as_global(ccx, expr, check_const::ConstQualif::empty(),
+                                   empty_substs, TrueConst::Yes) {
+        Err(Runtime(err)) => {
+            ccx.tcx().sess.span_err(expr.span, &err.description());
+            Err(Compiletime(err))
+        },
+        other => other,
+    }
 }
 
 pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                           expr: &hir::Expr,
                                           qualif: check_const::ConstQualif,
-                                          param_substs: &'tcx Substs<'tcx>)
-                                          -> ValueRef {
+                                          param_substs: &'tcx Substs<'tcx>,
+                                          trueconst: TrueConst)
+                                          -> Result<ValueRef, ConstEvalFailure> {
     debug!("get_const_expr_as_global: {:?}", expr.id);
     // Special-case constants to cache a common global for all uses.
     match expr.node {
@@ -250,17 +306,20 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     let key = (expr.id, param_substs);
     match ccx.const_values().borrow().get(&key) {
-        Some(&val) => return val,
+        Some(&val) => return Ok(val),
         None => {}
     }
+    let ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs,
+                                              &ccx.tcx().expr_ty(expr));
     let val = if qualif.intersects(check_const::ConstQualif::NON_STATIC_BORROWS) {
         // Avoid autorefs as they would create global instead of stack
         // references, even when only the latter are correct.
-        let ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs,
-                                                  &ccx.tcx().expr_ty(expr));
-        const_expr_unadjusted(ccx, expr, ty, param_substs, None)
+        try!(const_expr_unadjusted(ccx, expr, ty, param_substs, None, trueconst))
     } else {
-        const_expr(ccx, expr, param_substs, None).0
+        match const_expr(ccx, expr, param_substs, None, trueconst) {
+            Err(err) => return Err(err),
+            Ok((ok, _)) => ok,
+        }
     };
 
     // boolean SSA values are i1, but they have to be stored in i8 slots,
@@ -273,19 +332,20 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         }
     };
 
-    let lvalue = addr_of(ccx, val, "const");
+    let lvalue = addr_of(ccx, val, type_of::align_of(ccx, ty), "const");
     ccx.const_values().borrow_mut().insert(key, lvalue);
-    lvalue
+    Ok(lvalue)
 }
 
 pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                             e: &hir::Expr,
                             param_substs: &'tcx Substs<'tcx>,
-                            fn_args: FnArgMap)
-                            -> (ValueRef, Ty<'tcx>) {
+                            fn_args: FnArgMap,
+                            trueconst: TrueConst)
+                            -> Result<(ValueRef, Ty<'tcx>), ConstEvalFailure> {
     let ety = monomorphize::apply_param_substs(cx.tcx(), param_substs,
                                                &cx.tcx().expr_ty(e));
-    let llconst = const_expr_unadjusted(cx, e, ety, param_substs, fn_args);
+    let llconst = try!(const_expr_unadjusted(cx, e, ety, param_substs, fn_args, trueconst));
     let mut llconst = llconst;
     let mut ety_adjusted = monomorphize::apply_param_substs(cx.tcx(), param_substs,
                                                             &cx.tcx().expr_ty_adjusted(e));
@@ -313,7 +373,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 if adj.autoderefs == 0 {
                     // Don't copy data to do a deref+ref
                     // (i.e., skip the last auto-deref).
-                    llconst = addr_of(cx, llconst, "autoref");
+                    llconst = addr_of(cx, llconst, type_of::align_of(cx, ty), "autoref");
                     ty = cx.tcx().mk_imm_ref(cx.tcx().mk_region(ty::ReStatic), ty);
                 }
             } else {
@@ -380,11 +440,11 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                          e, ety_adjusted,
                          csize, tsize));
     }
-    (llconst, ety_adjusted)
+    Ok((llconst, ety_adjusted))
 }
 
 fn check_unary_expr_validity(cx: &CrateContext, e: &hir::Expr, t: Ty,
-                             te: ValueRef) {
+                             te: ValueRef, trueconst: TrueConst) -> Result<(), ConstEvalFailure> {
     // The only kind of unary expression that we check for validity
     // here is `-expr`, to check if it "overflows" (e.g. `-i32::MIN`).
     if let hir::ExprUnary(hir::UnNeg, ref inner_e) = e.node {
@@ -397,13 +457,13 @@ fn check_unary_expr_validity(cx: &CrateContext, e: &hir::Expr, t: Ty,
         //
         // Catch this up front by looking for ExprLit directly,
         // and just accepting it.
-        if let hir::ExprLit(_) = inner_e.node { return; }
+        if let hir::ExprLit(_) = inner_e.node { return Ok(()); }
 
         let result = match t.sty {
             ty::TyInt(int_type) => {
                 let input = match const_to_opt_int(te) {
                     Some(v) => v,
-                    None => return,
+                    None => return Ok(()),
                 };
                 const_int_checked_neg(
                     input, e, Some(const_eval::IntTy::from(cx.tcx(), int_type)))
@@ -411,31 +471,51 @@ fn check_unary_expr_validity(cx: &CrateContext, e: &hir::Expr, t: Ty,
             ty::TyUint(uint_type) => {
                 let input = match const_to_opt_uint(te) {
                     Some(v) => v,
-                    None => return,
+                    None => return Ok(()),
                 };
                 const_uint_checked_neg(
                     input, e, Some(const_eval::UintTy::from(cx.tcx(), uint_type)))
             }
-            _ => return,
+            _ => return Ok(()),
         };
+        const_err(cx, e, result, trueconst)
+    } else {
+        Ok(())
+    }
+}
 
-        // We do not actually care about a successful result.
-        if let Err(err) = result {
+fn const_err(cx: &CrateContext,
+             e: &hir::Expr,
+             result: Result<ConstVal, ConstEvalErr>,
+             trueconst: TrueConst)
+             -> Result<(), ConstEvalFailure> {
+    match (result, trueconst) {
+        (Ok(_), _) => {
+            // We do not actually care about a successful result.
+            Ok(())
+        },
+        (Err(err), TrueConst::Yes) => {
             cx.tcx().sess.span_err(e.span, &err.description());
-        }
+            Err(Compiletime(err))
+        },
+        (Err(err), TrueConst::No) => {
+            cx.tcx().sess.span_warn(e.span, &err.description());
+            Err(Runtime(err))
+        },
     }
 }
 
 fn check_binary_expr_validity(cx: &CrateContext, e: &hir::Expr, t: Ty,
-                              te1: ValueRef, te2: ValueRef) {
-    let b = if let hir::ExprBinary(b, _, _) = e.node { b } else { return };
+                              te1: ValueRef, te2: ValueRef,
+                              trueconst: TrueConst) -> Result<(), ConstEvalFailure> {
+    let b = if let hir::ExprBinary(b, _, _) = e.node { b } else { unreachable!() };
 
     let result = match t.sty {
         ty::TyInt(int_type) => {
             let (lhs, rhs) = match (const_to_opt_int(te1),
                                     const_to_opt_int(te2)) {
                 (Some(v1), Some(v2)) => (v1, v2),
-                _ => return,
+                _ => return Ok(()),
             };
 
             let opt_ety = Some(const_eval::IntTy::from(cx.tcx(), int_type));
@@ -447,14 +527,14 @@ fn check_binary_expr_validity(cx: &CrateContext, e: &hir::Expr, t: Ty,
                 hir::BiRem => const_int_checked_rem(lhs, rhs, e, opt_ety),
                 hir::BiShl => const_int_checked_shl(lhs, rhs, e, opt_ety),
                 hir::BiShr => const_int_checked_shr(lhs, rhs, e, opt_ety),
-                _ => return,
+                _ => return Ok(()),
             }
         }
         ty::TyUint(uint_type) => {
             let (lhs, rhs) = match (const_to_opt_uint(te1),
                                     const_to_opt_uint(te2)) {
                 (Some(v1), Some(v2)) => (v1, v2),
-                _ => return,
+                _ => return Ok(()),
             };
 
             let opt_ety = Some(const_eval::UintTy::from(cx.tcx(), uint_type));
@@ -466,43 +546,44 @@ fn check_binary_expr_validity(cx: &CrateContext, e: &hir::Expr, t: Ty,
                 hir::BiRem => const_uint_checked_rem(lhs, rhs, e, opt_ety),
                 hir::BiShl => const_uint_checked_shl(lhs, rhs, e, opt_ety),
                 hir::BiShr => const_uint_checked_shr(lhs, rhs, e, opt_ety),
-                _ => return,
+                _ => return Ok(()),
             }
         }
-        _ => return,
+        _ => return Ok(()),
     };
-    // We do not actually care about a successful result.
-    if let Err(err) = result {
-        cx.tcx().sess.span_err(e.span, &err.description());
-    }
+    const_err(cx, e, result, trueconst)
 }
 
 fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                    e: &hir::Expr,
                                    ety: Ty<'tcx>,
                                    param_substs: &'tcx Substs<'tcx>,
-                                   fn_args: FnArgMap)
-                                   -> ValueRef
+                                   fn_args: FnArgMap,
+                                   trueconst: TrueConst)
+                                   -> Result<ValueRef, ConstEvalFailure>
 {
     debug!("const_expr_unadjusted(e={:?}, ety={:?}, param_substs={:?})",
            e,
            ety,
            param_substs);
 
-    let map_list = |exprs: &[P<hir::Expr>]| -> Vec<ValueRef> {
+    let map_list = |exprs: &[P<hir::Expr>]| -> Result<Vec<ValueRef>, ConstEvalFailure> {
         exprs.iter()
-             .map(|e| const_expr(cx, &**e, param_substs, fn_args).0)
+             .map(|e| const_expr(cx, &**e, param_substs, fn_args, trueconst).map(|(l, _)| l))
+             .collect::<Vec<Result<ValueRef, ConstEvalFailure>>>()
+             .into_iter()
              .collect()
+         // this dance is necessary to eagerly run const_expr so all errors are reported
     };
     let _icx = push_ctxt("const_expr");
-    match e.node {
+    Ok(match e.node {
         hir::ExprLit(ref lit) => {
             const_lit(cx, e, &**lit)
         },
         hir::ExprBinary(b, ref e1, ref e2) => {
             /* Neither type is bottom, and we expect them to be unified
              * already, so the following is safe. */
-            let (te1, ty) = const_expr(cx, &**e1, param_substs, fn_args);
+            let (te1, ty) = try!(const_expr(cx, &**e1, param_substs, fn_args, trueconst));
             debug!("const_expr_unadjusted: te1={}, ty={:?}",
                    cx.tn().val_to_string(te1),
                    ty);
@@ -510,9 +591,9 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let is_float = ty.is_fp();
             let signed = ty.is_signed();
 
-            let (te2, _) = const_expr(cx, &**e2, param_substs, fn_args);
+            let (te2, _) = try!(const_expr(cx, &**e2, param_substs, fn_args, trueconst));
 
-            check_binary_expr_validity(cx, e, ty, te1, te2);
+            try!(check_binary_expr_validity(cx, e, ty, te1, te2, trueconst));
 
             unsafe { match b.node {
                 hir::BiAdd if is_float => llvm::LLVMConstFAdd(te1, te2),
@@ -558,35 +639,34 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             } } // unsafe { match b.node {
         },
         hir::ExprUnary(u, ref inner_e) => {
-            let (te, ty) = const_expr(cx, &**inner_e, param_substs, fn_args);
+            let (te, ty) = try!(const_expr(cx, &**inner_e, param_substs, fn_args, trueconst));
 
-            check_unary_expr_validity(cx, e, ty, te);
+            try!(check_unary_expr_validity(cx, e, ty, te, trueconst));
 
             let is_float = ty.is_fp();
             unsafe { match u {
-                hir::UnUniq | hir::UnDeref => const_deref(cx, te, ty).0,
-                hir::UnNot                 => llvm::LLVMConstNot(te),
-                hir::UnNeg if is_float     => llvm::LLVMConstFNeg(te),
-                hir::UnNeg                 => llvm::LLVMConstNeg(te),
+                hir::UnDeref           => const_deref(cx, te, ty).0,
+                hir::UnNot             => llvm::LLVMConstNot(te),
+                hir::UnNeg if is_float => llvm::LLVMConstFNeg(te),
+                hir::UnNeg             => llvm::LLVMConstNeg(te),
             } }
         },
         hir::ExprField(ref base, field) => {
-            let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args);
+            let (bv, bt) = try!(const_expr(cx, &**base, param_substs, fn_args, trueconst));
             let brepr = adt::represent_type(cx, bt);
             let vinfo = VariantInfo::from_ty(cx.tcx(), bt, None);
-            let ix = vinfo.field_index(field.node.name);
+            let ix = vinfo.field_index(field.node);
             adt::const_get_field(cx, &*brepr, bv, vinfo.discr, ix)
         },
         hir::ExprTupField(ref base, idx) => {
-            let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args);
+            let (bv, bt) = try!(const_expr(cx, &**base, param_substs, fn_args, trueconst));
             let brepr = adt::represent_type(cx, bt);
             let vinfo = VariantInfo::from_ty(cx.tcx(), bt, None);
             adt::const_get_field(cx, &*brepr, bv, vinfo.discr, idx.node)
         },
-
         hir::ExprIndex(ref base, ref index) => {
-            let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args);
-            let iv = match eval_const_expr_partial(cx.tcx(), &index, ExprTypeChecked) {
+            let (bv, bt) = try!(const_expr(cx, &**base, param_substs, fn_args, trueconst));
+            let iv = match eval_const_expr_partial(cx.tcx(), &index, ExprTypeChecked, None) {
                 Ok(ConstVal::Int(i)) => i as u64,
                 Ok(ConstVal::Uint(u)) => u,
                 _ => cx.sess().span_bug(index.span,
@@ -627,9 +707,9 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             if iv >= len {
                 // FIXME #3170: report this earlier on in the const-eval
                 // pass. Reporting here is a bit late.
-                cx.sess().span_err(e.span,
-                                   "const index-expr is out of bounds");
-                C_undef(type_of::type_of(cx, bt).element_type())
+                span_err!(cx.sess(), e.span, E0515,
+                          "const index-expr is out of bounds");
+                C_undef(val_ty(arr).element_type())
             } else {
                 const_get_elt(cx, arr, &[iv as c_uint])
             }
@@ -637,10 +717,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         hir::ExprCast(ref base, _) => {
             let t_cast = ety;
             let llty = type_of::type_of(cx, t_cast);
-            let (v, t_expr) = const_expr(cx, &**base, param_substs, fn_args);
+            let (v, t_expr) = try!(const_expr(cx, &**base, param_substs, fn_args, trueconst));
             debug!("trans_const_cast({:?} as {:?})", t_expr, t_cast);
             if expr::cast_is_noop(cx.tcx(), base, t_expr, t_cast) {
-                return v;
+                return Ok(v);
             }
             if type_is_fat_ptr(cx.tcx(), t_expr) {
                 // Fat pointer casts.
@@ -651,9 +731,9 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                    ptr_ty);
                 if type_is_fat_ptr(cx.tcx(), t_cast) {
                     let info = const_get_elt(cx, v, &[abi::FAT_PTR_EXTRA as u32]);
-                    return C_struct(cx, &[addr, info], false)
+                    return Ok(C_struct(cx, &[addr, info], false))
                 } else {
-                    return addr;
+                    return Ok(addr);
                 }
             }
             unsafe { match (
@@ -703,7 +783,6 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let mut cur = sub;
             loop {
                 match cur.node {
-                    hir::ExprParen(ref sub) => cur = sub,
                     hir::ExprBlock(ref blk) => {
                         if let Some(ref sub) = blk.expr {
                             cur = sub;
@@ -720,35 +799,47 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             } else {
                 // If this isn't the address of a static, then keep going through
                 // normal constant evaluation.
-                let (v, _) = const_expr(cx, &**sub, param_substs, fn_args);
-                addr_of(cx, v, "ref")
+                let (v, ty) = try!(const_expr(cx, &**sub, param_substs, fn_args, trueconst));
+                addr_of(cx, v, type_of::align_of(cx, ty), "ref")
             }
         },
         hir::ExprAddrOf(hir::MutMutable, ref sub) => {
-            let (v, _) = const_expr(cx, &**sub, param_substs, fn_args);
-            addr_of_mut(cx, v, "ref_mut_slice")
+            let (v, ty) = try!(const_expr(cx, &**sub, param_substs, fn_args, trueconst));
+            addr_of_mut(cx, v, type_of::align_of(cx, ty), "ref_mut_slice")
         },
         hir::ExprTup(ref es) => {
             let repr = adt::represent_type(cx, ety);
-            let vals = map_list(&es[..]);
+            let vals = try!(map_list(&es[..]));
             adt::trans_const(cx, &*repr, 0, &vals[..])
         },
         hir::ExprStruct(_, ref fs, ref base_opt) => {
             let repr = adt::represent_type(cx, ety);
 
             let base_val = match *base_opt {
-                Some(ref base) => Some(const_expr(cx, &**base, param_substs, fn_args)),
+                Some(ref base) => Some(try!(const_expr(
+                    cx,
+                    &**base,
+                    param_substs,
+                    fn_args,
+                    trueconst,
+                ))),
                 None => None
             };
 
             let VariantInfo { discr, fields } = VariantInfo::of_node(cx.tcx(), ety, e.id);
             let cs = fields.iter().enumerate().map(|(ix, &Field(f_name, _))| {
-                match (fs.iter().find(|f| f_name == f.ident.node.name), base_val) {
-                    (Some(ref f), _) => const_expr(cx, &*f.expr, param_substs, fn_args).0,
-                    (_, Some((bv, _))) => adt::const_get_field(cx, &*repr, bv, discr, ix),
+                match (fs.iter().find(|f| f_name == f.name.node), base_val) {
+                    (Some(ref f), _) => {
+                        const_expr(cx, &*f.expr, param_substs, fn_args, trueconst).map(|(l, _)| l)
+                    },
+                    (_, Some((bv, _))) => Ok(adt::const_get_field(cx, &*repr, bv, discr, ix)),
                     (_, None) => cx.sess().span_bug(e.span, "missing struct field"),
                 }
-            }).collect::<Vec<_>>();
+            })
+            .collect::<Vec<Result<_, ConstEvalFailure>>>()
+            .into_iter()
+            .collect::<Result<Vec<_>,ConstEvalFailure>>();
+            let cs = try!(cs);
             if ety.is_simd() {
                 C_vector(&cs[..])
             } else {
@@ -759,8 +850,17 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let unit_ty = ety.sequence_element_type(cx.tcx());
             let llunitty = type_of::type_of(cx, unit_ty);
             let vs = es.iter()
-                       .map(|e| const_expr(cx, &**e, param_substs, fn_args).0)
-                       .collect::<Vec<_>>();
+                       .map(|e| const_expr(
+                           cx,
+                           &**e,
+                           param_substs,
+                           fn_args,
+                           trueconst,
+                       ).map(|(l, _)| l))
+                       .collect::<Vec<Result<_, ConstEvalFailure>>>()
+                       .into_iter()
+                       .collect::<Result<Vec<_>, ConstEvalFailure>>();
+            let vs = try!(vs);
             // If the vector contains enums, an LLVM array won't work.
             if vs.iter().any(|vi| val_ty(*vi) != llunitty) {
                 C_struct(cx, &vs[..], false)
@@ -772,7 +872,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let unit_ty = ety.sequence_element_type(cx.tcx());
             let llunitty = type_of::type_of(cx, unit_ty);
             let n = cx.tcx().eval_repeat_count(count);
-            let unit_val = const_expr(cx, &**elem, param_substs, fn_args).0;
+            let unit_val = try!(const_expr(cx, &**elem, param_substs, fn_args, trueconst)).0;
             let vs = vec![unit_val; n];
             if val_ty(unit_val) != llunitty {
                 C_struct(cx, &vs[..], false)
@@ -783,7 +883,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         hir::ExprPath(..) => {
             let def = cx.tcx().def_map.borrow().get(&e.id).unwrap().full_def();
             match def {
-                def::DefLocal(id) => {
+                def::DefLocal(_, id) => {
                     if let Some(val) = fn_args.and_then(|args| args.get(&id).cloned()) {
                         val
                     } else {
@@ -794,7 +894,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
                 }
                 def::DefConst(def_id) | def::DefAssociatedConst(def_id) => {
-                    const_deref_ptr(cx, get_const_val(cx, def_id, e))
+                    const_deref_ptr(cx, try!(get_const_val(cx, def_id, e)))
                 }
                 def::DefVariant(enum_did, variant_did, _) => {
                     let vinfo = cx.tcx().lookup_adt_def(enum_did).variant_with_id(variant_did);
@@ -806,7 +906,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         ty::VariantKind::Tuple => {
                             expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
                         }
-                        ty::VariantKind::Dict => {
+                        ty::VariantKind::Struct => {
                             cx.sess().span_bug(e.span, "path-expr refers to a dict variant!")
                         }
                     }
@@ -830,7 +930,6 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let mut callee = &**callee;
             loop {
                 callee = match callee.node {
-                    hir::ExprParen(ref inner) => &**inner,
                     hir::ExprBlock(ref block) => match block.expr {
                         Some(ref tail) => &**tail,
                         None => break,
@@ -839,10 +938,17 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 };
             }
             let def = cx.tcx().def_map.borrow()[&callee.id].full_def();
-            let arg_vals = map_list(args);
+            let arg_vals = try!(map_list(args));
             match def {
                 def::DefFn(did, _) | def::DefMethod(did) => {
-                    const_fn_call(cx, ExprId(callee.id), did, &arg_vals, param_substs)
+                    try!(const_fn_call(
+                        cx,
+                        ExprId(callee.id),
+                        did,
+                        &arg_vals,
+                        param_substs,
+                        trueconst,
+                    ))
                 }
                 def::DefStruct(_) => {
                     if ety.is_simd() {
@@ -864,24 +970,29 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             }
         },
         hir::ExprMethodCall(_, _, ref args) => {
-            let arg_vals = map_list(args);
+            let arg_vals = try!(map_list(args));
             let method_call = ty::MethodCall::expr(e.id);
             let method_did = cx.tcx().tables.borrow().method_map[&method_call].def_id;
-            const_fn_call(cx, MethodCallKey(method_call),
-                          method_did, &arg_vals, param_substs)
+            try!(const_fn_call(cx, MethodCallKey(method_call),
+                               method_did, &arg_vals, param_substs, trueconst))
         },
-        hir::ExprParen(ref e) => const_expr(cx, &**e, param_substs, fn_args).0,
         hir::ExprBlock(ref block) => {
             match block.expr {
-                Some(ref expr) => const_expr(cx, &**expr, param_substs, fn_args).0,
+                Some(ref expr) => try!(const_expr(
+                    cx,
+                    &**expr,
+                    param_substs,
+                    fn_args,
+                    trueconst,
+                )).0,
                 None => C_nil(cx),
             }
         },
         hir::ExprClosure(_, ref decl, ref body) => {
             match ety.sty {
-                ty::TyClosure(_, ref substs) => {
+                ty::TyClosure(def_id, ref substs) => {
                     closure::trans_closure_expr(closure::Dest::Ignore(cx), decl,
-                                                body, e.id, substs);
+                                                body, e.id, def_id, substs);
                 }
                 _ =>
                     cx.sess().span_bug(
@@ -892,20 +1003,27 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         },
         _ => cx.sess().span_bug(e.span,
                                 "bad constant expression type in consts::const_expr"),
-    }
+    })
 }
+
 pub fn trans_static(ccx: &CrateContext,
                     m: hir::Mutability,
                     expr: &hir::Expr,
                     id: ast::NodeId,
-                    attrs: &Vec<hir::Attribute>)
-                    -> ValueRef {
+                    attrs: &Vec<ast::Attribute>)
+                    -> Result<ValueRef, ConstEvalErr> {
     unsafe {
         let _icx = push_ctxt("trans_static");
         let g = base::get_item_val(ccx, id);
 
         let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
-        let (v, _) = const_expr(ccx, expr, empty_substs, None);
+        let (v, _) = try!(const_expr(
+            ccx,
+            expr,
+            empty_substs,
+            None,
+            TrueConst::Yes,
+        ).map_err(|e| e.into_inner()));
 
         // boolean SSA values are i1, but they have to be stored in i8 slots,
         // otherwise some LLVM optimization passes don't work as expected
@@ -936,6 +1054,7 @@ pub fn trans_static(ccx: &CrateContext,
             ccx.statics_to_rauw().borrow_mut().push((g, new_g));
             new_g
         };
+        llvm::LLVMSetAlignment(g, type_of::align_of(ccx, ty));
         llvm::LLVMSetInitializer(g, v);
 
         // As an optimization, all shared statics which do not have interior
@@ -953,7 +1072,7 @@ pub fn trans_static(ccx: &CrateContext,
                                "thread_local") {
             llvm::set_thread_local(g, true);
         }
-        g
+        Ok(g)
     }
 }
 
@@ -962,6 +1081,9 @@ fn get_static_val<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                             did: DefId,
                             ty: Ty<'tcx>)
                             -> ValueRef {
-    if did.is_local() { return base::get_item_val(ccx, did.node) }
-    base::trans_external_path(ccx, did, ty)
+    if let Some(node_id) = ccx.tcx().map.as_local_node_id(did) {
+        base::get_item_val(ccx, node_id)
+    } else {
+        base::trans_external_path(ccx, did, ty)
+    }
 }
index 94ce92ab972f492264cd6d3b5701bfde33b56af9..b92e02fec5c4d0b2c83cf7b62478484199d2625d 100644 (file)
@@ -838,7 +838,6 @@ fn declare_intrinsic(ccx: &CrateContext, key: &str) -> Option<ValueRef> {
 
     ifn!("llvm.trap", fn() -> void);
     ifn!("llvm.debugtrap", fn() -> void);
-    ifn!("llvm.frameaddress", fn(t_i32) -> i8p);
 
     ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32);
     ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64);
index 340eabf77daec4c57126f5378177a10885181211..5f83abc065fed327adde9fb7a980c54efa235c28 100644 (file)
@@ -22,6 +22,7 @@ use trans::consts;
 use trans::debuginfo;
 use trans::debuginfo::{DebugLoc, ToDebugLoc};
 use trans::expr;
+use trans::machine;
 use trans;
 use middle::ty;
 
@@ -305,7 +306,7 @@ pub fn trans_loop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
 pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                     expr: &hir::Expr,
-                                    opt_label: Option<ast::Ident>,
+                                    opt_label: Option<ast::Name>,
                                     exit: usize)
                                     -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_break_cont");
@@ -338,14 +339,14 @@ pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
 pub fn trans_break<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                expr: &hir::Expr,
-                               label_opt: Option<ast::Ident>)
+                               label_opt: Option<ast::Name>)
                                -> Block<'blk, 'tcx> {
     return trans_break_cont(bcx, expr, label_opt, cleanup::EXIT_BREAK);
 }
 
 pub fn trans_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                               expr: &hir::Expr,
-                              label_opt: Option<ast::Ident>)
+                              label_opt: Option<ast::Name>)
                               -> Block<'blk, 'tcx> {
     return trans_break_cont(bcx, expr, label_opt, cleanup::EXIT_LOOP);
 }
@@ -401,7 +402,8 @@ pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let filename = C_str_slice(ccx, filename);
     let line = C_u32(ccx, loc.line as u32);
     let expr_file_line_const = C_struct(ccx, &[v_str, filename, line], false);
-    let expr_file_line = consts::addr_of(ccx, expr_file_line_const, "panic_loc");
+    let align = machine::llalign_of_min(ccx, val_ty(expr_file_line_const));
+    let expr_file_line = consts::addr_of(ccx, expr_file_line_const, align, "panic_loc");
     let args = vec!(expr_file_line);
     let did = langcall(bcx, Some(call_info.span), "", PanicFnLangItem);
     let bcx = callee::trans_lang_call(bcx,
@@ -433,7 +435,8 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let filename = C_str_slice(ccx,  filename);
     let line = C_u32(ccx, loc.line as u32);
     let file_line_const = C_struct(ccx, &[filename, line], false);
-    let file_line = consts::addr_of(ccx, file_line_const, "panic_bounds_check_loc");
+    let align = machine::llalign_of_min(ccx, val_ty(file_line_const));
+    let file_line = consts::addr_of(ccx, file_line_const, align, "panic_bounds_check_loc");
     let args = vec!(file_line, index, len);
     let did = langcall(bcx, Some(call_info.span), "", PanicBoundsCheckFnLangItem);
     let bcx = callee::trans_lang_call(bcx,
index ca616b5622a64f38de53039233db4d528bc47a9b..7597d5f92aec05b6128c5e7e4f82f600e31a4b0e 100644 (file)
@@ -49,7 +49,7 @@ pub fn create_scope_map(cx: &CrateContext,
     for arg in args {
         pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, _, path1| {
             scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata,
-                                               name: Some(path1.node.name) });
+                                               name: Some(path1.node) });
             scope_map.insert(node_id, fn_metadata);
         })
     }
@@ -322,13 +322,10 @@ fn walk_expr(cx: &CrateContext,
         hir::ExprCast(ref sub_exp, _)     |
         hir::ExprAddrOf(_, ref sub_exp)  |
         hir::ExprField(ref sub_exp, _) |
-        hir::ExprTupField(ref sub_exp, _) |
-        hir::ExprParen(ref sub_exp) =>
+        hir::ExprTupField(ref sub_exp, _) =>
             walk_expr(cx, &**sub_exp, scope_stack, scope_map),
 
-        hir::ExprBox(ref place, ref sub_expr) => {
-            place.as_ref().map(
-                |e| walk_expr(cx, &**e, scope_stack, scope_map));
+        hir::ExprBox(ref sub_expr) => {
             walk_expr(cx, &**sub_expr, scope_stack, scope_map);
         }
 
index 3d330fc1c7116df59496d6633f14fd266b919102..03b58fb2c474f777415d8b5095b03ccfe7f66df8 100644 (file)
 use llvm;
 use llvm::ValueRef;
 
-use trans::common::{C_bytes, CrateContext};
+use trans::common::{C_bytes, CrateContext, C_i32};
 use trans::declare;
 use trans::type_::Type;
 use session::config::NoDebugInfo;
 
 use std::ffi::CString;
 use std::ptr;
-use rustc_front::attr;
+use syntax::attr;
 
 
 /// Inserts a side-effect free instruction sequence that makes sure that the
@@ -31,11 +31,21 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext)
         let gdb_debug_scripts_section_global =
             get_or_insert_gdb_debug_scripts_section_global(ccx);
         unsafe {
+            // Load just the first byte as that's all that's necessary to force
+            // LLVM to keep around the reference to the global.
+            let indices = [C_i32(ccx, 0), C_i32(ccx, 0)];
+            let element =
+                llvm::LLVMBuildInBoundsGEP(ccx.raw_builder(),
+                                           gdb_debug_scripts_section_global,
+                                           indices.as_ptr(),
+                                           indices.len() as ::libc::c_uint,
+                                           empty.as_ptr());
             let volative_load_instruction =
                 llvm::LLVMBuildLoad(ccx.raw_builder(),
-                                    gdb_debug_scripts_section_global,
+                                    element,
                                     empty.as_ptr());
             llvm::LLVMSetVolatile(volative_load_instruction, llvm::True);
+            llvm::LLVMSetAlignment(volative_load_instruction, 1);
         }
     }
 }
@@ -44,11 +54,12 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext)
 /// section.
 pub fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
                                                   -> llvm::ValueRef {
-    let section_var_name = "__rustc_debug_gdb_scripts_section__";
+    let c_section_var_name = "__rustc_debug_gdb_scripts_section__\0";
+    let section_var_name = &c_section_var_name[..c_section_var_name.len()-1];
 
     let section_var = unsafe {
         llvm::LLVMGetNamedGlobal(ccx.llmod(),
-                                 section_var_name.as_ptr() as *const _)
+                                 c_section_var_name.as_ptr() as *const _)
     };
 
     if section_var == ptr::null_mut() {
index a68eab953c3fa5a8d96af154bcffbbf98d7cb310..2e7b1f31ba9bc8f73935d3ccbda82da1b99092e2 100644 (file)
@@ -27,7 +27,6 @@ use middle::def_id::DefId;
 use middle::pat_util;
 use middle::subst::{self, Substs};
 use rustc::front::map as hir_map;
-use rustc_front;
 use rustc_front::hir;
 use trans::{type_of, adt, machine, monomorphize};
 use trans::common::{self, CrateContext, FunctionContext, Block};
@@ -43,6 +42,7 @@ use std::ffi::CString;
 use std::path::Path;
 use std::ptr;
 use std::rc::Rc;
+use syntax;
 use syntax::util::interner::Interner;
 use syntax::codemap::Span;
 use syntax::{ast, codemap};
@@ -324,8 +324,8 @@ impl<'tcx> TypeMap<'tcx> {
                                             output: &mut String) {
             // First, find out the 'real' def_id of the type. Items inlined from
             // other crates have to be mapped back to their source.
-            let source_def_id = if def_id.is_local() {
-                match cx.external_srcs().borrow().get(&def_id.node).cloned() {
+            let source_def_id = if let Some(node_id) = cx.tcx().map.as_local_node_id(def_id) {
+                match cx.external_srcs().borrow().get(&node_id).cloned() {
                     Some(source_def_id) => {
                         // The given def_id identifies the inlined copy of a
                         // type definition, let's take the source of the copy.
@@ -346,7 +346,7 @@ impl<'tcx> TypeMap<'tcx> {
 
             output.push_str(crate_hash.as_str());
             output.push_str("/");
-            output.push_str(&format!("{:x}", def_id.node));
+            output.push_str(&format!("{:x}", def_id.index.as_usize()));
 
             // Maybe check that there is no self type here.
 
@@ -480,7 +480,7 @@ macro_rules! return_if_metadata_created_in_meantime {
                                 .find_metadata_for_unique_id($unique_type_id) {
             Some(metadata) => return MetadataCreationResult::new(metadata, true),
             None => { /* proceed normally */ }
-        };
+        }
     )
 }
 
@@ -809,7 +809,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         let mut type_map = debug_context(cx).type_map.borrow_mut();
 
         if already_stored_in_typemap {
-            // Also make sure that we already have a TypeMap entry entry for the unique type id.
+            // Also make sure that we already have a TypeMap entry for the unique type id.
             let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) {
                 Some(metadata) => metadata,
                 None => {
@@ -934,22 +934,22 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::TyBool => ("bool".to_string(), DW_ATE_boolean),
         ty::TyChar => ("char".to_string(), DW_ATE_unsigned_char),
         ty::TyInt(int_ty) => match int_ty {
-            hir::TyIs => ("isize".to_string(), DW_ATE_signed),
-            hir::TyI8 => ("i8".to_string(), DW_ATE_signed),
-            hir::TyI16 => ("i16".to_string(), DW_ATE_signed),
-            hir::TyI32 => ("i32".to_string(), DW_ATE_signed),
-            hir::TyI64 => ("i64".to_string(), DW_ATE_signed)
+            ast::TyIs => ("isize".to_string(), DW_ATE_signed),
+            ast::TyI8 => ("i8".to_string(), DW_ATE_signed),
+            ast::TyI16 => ("i16".to_string(), DW_ATE_signed),
+            ast::TyI32 => ("i32".to_string(), DW_ATE_signed),
+            ast::TyI64 => ("i64".to_string(), DW_ATE_signed)
         },
         ty::TyUint(uint_ty) => match uint_ty {
-            hir::TyUs => ("usize".to_string(), DW_ATE_unsigned),
-            hir::TyU8 => ("u8".to_string(), DW_ATE_unsigned),
-            hir::TyU16 => ("u16".to_string(), DW_ATE_unsigned),
-            hir::TyU32 => ("u32".to_string(), DW_ATE_unsigned),
-            hir::TyU64 => ("u64".to_string(), DW_ATE_unsigned)
+            ast::TyUs => ("usize".to_string(), DW_ATE_unsigned),
+            ast::TyU8 => ("u8".to_string(), DW_ATE_unsigned),
+            ast::TyU16 => ("u16".to_string(), DW_ATE_unsigned),
+            ast::TyU32 => ("u32".to_string(), DW_ATE_unsigned),
+            ast::TyU64 => ("u64".to_string(), DW_ATE_unsigned)
         },
         ty::TyFloat(float_ty) => match float_ty {
-            hir::TyF32 => ("f32".to_string(), DW_ATE_float),
-            hir::TyF64 => ("f64".to_string(), DW_ATE_float),
+            ast::TyF32 => ("f32".to_string(), DW_ATE_float),
+            ast::TyF64 => ("f64".to_string(), DW_ATE_float),
         },
         _ => cx.sess().bug("debuginfo::basic_type_metadata - t is invalid type")
     };
@@ -1365,7 +1365,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
                 let sole_struct_member_description = MemberDescription {
                     name: match non_null_variant.kind() {
                         ty::VariantKind::Tuple => "__0".to_string(),
-                        ty::VariantKind::Dict => {
+                        ty::VariantKind::Struct => {
                             non_null_variant.fields[0].name.to_string()
                         }
                         ty::VariantKind::Unit => unreachable!()
@@ -1540,7 +1540,7 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                    .map(|(i, _)| format!("__{}", i))
                    .collect()
         }
-        ty::VariantKind::Dict => {
+        ty::VariantKind::Struct => {
             variant.fields
                    .iter()
                    .map(|f| f.name.to_string())
@@ -1608,7 +1608,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         })
         .collect();
 
-    let discriminant_type_metadata = |inttype: rustc_front::attr::IntType| {
+    let discriminant_type_metadata = |inttype: syntax::attr::IntType| {
         let disr_type_key = (enum_def_id, inttype);
         let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
                                                                  .borrow()
@@ -1858,8 +1858,8 @@ pub fn create_global_var_metadata(cx: &CrateContext,
     let (name, span) = match var_item {
         hir_map::NodeItem(item) => {
             match item.node {
-                hir::ItemStatic(..) => (item.ident.name, item.span),
-                hir::ItemConst(..) => (item.ident.name, item.span),
+                hir::ItemStatic(..) => (item.name, item.span),
+                hir::ItemConst(..) => (item.name, item.span),
                 _ => {
                     cx.sess()
                       .span_bug(item.span,
@@ -1887,7 +1887,8 @@ pub fn create_global_var_metadata(cx: &CrateContext,
     let is_local_to_unit = is_node_local_to_unit(cx, node_id);
     let variable_type = cx.tcx().node_id_to_type(node_id);
     let type_metadata = type_metadata(cx, variable_type, span);
-    let namespace_node = namespace_for_item(cx, DefId::local(node_id));
+    let node_def_id = cx.tcx().map.local_def_id(node_id);
+    let namespace_node = namespace_for_item(cx, node_def_id);
     let var_name = name.to_string();
     let linkage_name =
         namespace_node.mangled_name_of_contained_item(&var_name[..]);
@@ -1925,7 +1926,7 @@ pub fn create_local_var_metadata(bcx: Block, local: &hir::Local) {
     let def_map = &cx.tcx().def_map;
     let locals = bcx.fcx.lllocals.borrow();
 
-    pat_util::pat_bindings(def_map, &*local.pat, |_, node_id, span, var_ident| {
+    pat_util::pat_bindings(def_map, &*local.pat, |_, node_id, span, var_name| {
         let datum = match locals.get(&node_id) {
             Some(datum) => datum,
             None => {
@@ -1943,7 +1944,7 @@ pub fn create_local_var_metadata(bcx: Block, local: &hir::Local) {
         let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
 
         declare_local(bcx,
-                      var_ident.node.name,
+                      var_name.node,
                       datum.ty,
                       scope_metadata,
                       VariableAccess::DirectVariable { alloca: datum.val },
@@ -1975,7 +1976,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         None => {
             cx.sess().span_bug(span, "debuginfo::create_captured_var_metadata: node not found");
         }
-        Some(hir_map::NodeLocal(pat)) | Some(hir_map::NodeArg(pat)) => {
+        Some(hir_map::NodeLocal(pat)) => {
             match pat.node {
                 hir::PatIdent(_, ref path1, _) => {
                     path1.node.name
@@ -2105,7 +2106,7 @@ pub fn create_argument_metadata(bcx: Block, arg: &hir::Arg) {
                          .fn_metadata;
     let locals = bcx.fcx.lllocals.borrow();
 
-    pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, var_ident| {
+    pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, var_name| {
         let datum = match locals.get(&node_id) {
             Some(v) => v,
             None => {
@@ -2132,7 +2133,7 @@ pub fn create_argument_metadata(bcx: Block, arg: &hir::Arg) {
         };
 
         declare_local(bcx,
-                      var_ident.node.name,
+                      var_name.node,
                       datum.ty,
                       scope_metadata,
                       VariableAccess::DirectVariable { alloca: datum.val },
index dbb1355c9e6123d4c0e68f4624689fadb3d486bf..a08f33c8899943ede12c914c26b98ecc22eb51d4 100644 (file)
@@ -31,7 +31,6 @@ use middle::infer::normalize_associated_type;
 use middle::subst::{self, Substs};
 use rustc_front;
 use rustc_front::hir;
-use rustc_front::attr::IntType;
 
 use trans::common::{NodeIdAndSpan, CrateContext, FunctionContext, Block};
 use trans;
@@ -49,6 +48,7 @@ use std::rc::Rc;
 
 use syntax::codemap::{Span, Pos};
 use syntax::{abi, ast, codemap};
+use syntax::attr::IntType;
 use syntax::parse::token::{self, special_idents};
 
 pub mod gdb;
@@ -242,7 +242,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
             match item.node {
                 hir::ItemFn(ref fn_decl, _, _, _, ref generics, ref top_level_block) => {
-                    (item.ident.name, fn_decl, generics, top_level_block, item.span, true)
+                    (item.name, fn_decl, generics, top_level_block, item.span, true)
                 }
                 _ => {
                     cx.sess().span_bug(item.span,
@@ -257,7 +257,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         return FunctionDebugContext::FunctionWithoutDebugInfo;
                     }
 
-                    (impl_item.ident.name,
+                    (impl_item.name,
                      &sig.decl,
                      &sig.generics,
                      body,
@@ -296,7 +296,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         return FunctionDebugContext::FunctionWithoutDebugInfo;
                     }
 
-                    (trait_item.ident.name,
+                    (trait_item.name,
                      &sig.decl,
                      &sig.generics,
                      body,
@@ -351,7 +351,8 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     // somehow (storing a path in the hir_map, or construct a path using the
     // enclosing function).
     let (linkage_name, containing_scope) = if has_path {
-        let namespace_node = namespace_for_item(cx, DefId::local(fn_ast_id));
+        let fn_ast_def_id = cx.tcx().map.local_def_id(fn_ast_id);
+        let namespace_node = namespace_for_item(cx, fn_ast_def_id);
         let linkage_name = namespace_node.mangled_name_of_contained_item(
             &function_name[..]);
         let containing_scope = namespace_node.scope;
@@ -520,7 +521,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
         // Handle other generic parameters
         let actual_types = param_substs.types.get_slice(subst::FnSpace);
-        for (index, &hir::TyParam{ ident, .. }) in generics.ty_params.iter().enumerate() {
+        for (index, &hir::TyParam{ name, .. }) in generics.ty_params.iter().enumerate() {
             let actual_type = actual_types[index];
             // Add actual type name to <...> clause of function name
             let actual_type_name = compute_debuginfo_type_name(cx,
@@ -535,7 +536,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             // Again, only create type information if full debuginfo is enabled
             if cx.sess().opts.debuginfo == FullDebugInfo {
                 let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
-                let name = CString::new(ident.name.as_str().as_bytes()).unwrap();
+                let name = CString::new(name.as_str().as_bytes()).unwrap();
                 let param_metadata = unsafe {
                     llvm::LLVMDIBuilderCreateTemplateTypeParameter(
                         DIB(cx),
index 425364407b51b6bc8b123b1abde42174e1e409e6..7400ec3cbcd4aceb19b7aeeda25f2ce99bdfe1b8 100644 (file)
@@ -18,7 +18,7 @@ use middle::subst::{self, Substs};
 use middle::ty::{self, Ty};
 
 use rustc_front::hir;
-
+use syntax::ast;
 
 // Compute the name of the type as it should be stored in debuginfo. Does not do
 // any caching, i.e. calling the function twice with the same type will also do
@@ -43,18 +43,18 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::TyBool              => output.push_str("bool"),
         ty::TyChar              => output.push_str("char"),
         ty::TyStr               => output.push_str("str"),
-        ty::TyInt(hir::TyIs)    => output.push_str("isize"),
-        ty::TyInt(hir::TyI8)    => output.push_str("i8"),
-        ty::TyInt(hir::TyI16)   => output.push_str("i16"),
-        ty::TyInt(hir::TyI32)   => output.push_str("i32"),
-        ty::TyInt(hir::TyI64)   => output.push_str("i64"),
-        ty::TyUint(hir::TyUs)   => output.push_str("usize"),
-        ty::TyUint(hir::TyU8)   => output.push_str("u8"),
-        ty::TyUint(hir::TyU16)  => output.push_str("u16"),
-        ty::TyUint(hir::TyU32)  => output.push_str("u32"),
-        ty::TyUint(hir::TyU64)  => output.push_str("u64"),
-        ty::TyFloat(hir::TyF32) => output.push_str("f32"),
-        ty::TyFloat(hir::TyF64) => output.push_str("f64"),
+        ty::TyInt(ast::TyIs)    => output.push_str("isize"),
+        ty::TyInt(ast::TyI8)    => output.push_str("i8"),
+        ty::TyInt(ast::TyI16)   => output.push_str("i16"),
+        ty::TyInt(ast::TyI32)   => output.push_str("i32"),
+        ty::TyInt(ast::TyI64)   => output.push_str("i64"),
+        ty::TyUint(ast::TyUs)   => output.push_str("usize"),
+        ty::TyUint(ast::TyU8)   => output.push_str("u8"),
+        ty::TyUint(ast::TyU16)  => output.push_str("u16"),
+        ty::TyUint(ast::TyU32)  => output.push_str("u32"),
+        ty::TyUint(ast::TyU64)  => output.push_str("u64"),
+        ty::TyFloat(ast::TyF32) => output.push_str("f32"),
+        ty::TyFloat(ast::TyF64) => output.push_str("f64"),
         ty::TyStruct(def, substs) |
         ty::TyEnum(def, substs) => {
             push_item_name(cx, def.did, qualified, output);
index c019a0a950cba5bfd9b0ef2cf3ab6686bf875912..276f9936ac52ad36ff5e129cf3f84390f14b191c 100644 (file)
@@ -21,8 +21,6 @@ use trans::machine;
 use trans::common::{CrateContext, FunctionContext};
 use trans::type_::Type;
 
-use rustc_front::hir;
-
 use syntax::codemap::Span;
 use syntax::{ast, codemap};
 
@@ -46,11 +44,11 @@ pub fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
     };
 }
 
-pub fn contains_nodebug_attribute(attributes: &[hir::Attribute]) -> bool {
+pub fn contains_nodebug_attribute(attributes: &[ast::Attribute]) -> bool {
     attributes.iter().any(|attr| {
-        let meta_item: &hir::MetaItem = &*attr.node.value;
+        let meta_item: &ast::MetaItem = &*attr.node.value;
         match meta_item.node {
-            hir::MetaWord(ref value) => &value[..] == "no_debug",
+            ast::MetaWord(ref value) => &value[..] == "no_debug",
             _ => false
         }
     })
@@ -101,12 +99,9 @@ pub fn assert_type_for_node_id(cx: &CrateContext,
 pub fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: DefId)
                                    -> (DIScope, Span) {
     let containing_scope = namespace_for_item(cx, def_id).scope;
-    let definition_span = if def_id.is_local() {
-        cx.tcx().map.span(def_id.node)
-    } else {
-        // For external items there is no span information
-        codemap::DUMMY_SP
-    };
+    let definition_span = cx.tcx().map.def_id_span(def_id, codemap::DUMMY_SP /* (1) */ );
+
+    // (1) For external items there is no span information
 
     (containing_scope, definition_span)
 }
index 7d8996867c016ff4138ec8425502ad2d6f49aeab..6144de7109fba4f7f7a0aa1b15a6324ad0225233 100644 (file)
@@ -83,7 +83,7 @@ use trans::type_::Type;
 use rustc_front;
 use rustc_front::hir;
 
-use syntax::{ast, codemap};
+use syntax::{ast, ast_util, codemap};
 use syntax::parse::token::InternedString;
 use syntax::ptr::P;
 use syntax::parse::token;
@@ -119,7 +119,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
 
-    if bcx.tcx().tables.borrow().adjustments.contains_key(&expr.id) {
+    if adjustment_required(bcx, expr) {
         // use trans, which may be less efficient but
         // which will perform the adjustments:
         let datum = unpack_datum!(bcx, trans(bcx, expr));
@@ -133,13 +133,25 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     ) {
         if !qualif.intersects(check_const::ConstQualif::PREFER_IN_PLACE) {
             if let SaveIn(lldest) = dest {
-                let global = consts::get_const_expr_as_global(bcx.ccx(), expr, qualif,
-                                                            bcx.fcx.param_substs);
-                // Cast pointer to destination, because constants
-                // have different types.
-                let lldest = PointerCast(bcx, lldest, val_ty(global));
-                memcpy_ty(bcx, lldest, global, expr_ty_adjusted(bcx, expr));
-                return bcx;
+                match consts::get_const_expr_as_global(bcx.ccx(), expr, qualif,
+                                                       bcx.fcx.param_substs,
+                                                       consts::TrueConst::No) {
+                    Ok(global) => {
+                        // Cast pointer to destination, because constants
+                        // have different types.
+                        let lldest = PointerCast(bcx, lldest, val_ty(global));
+                        memcpy_ty(bcx, lldest, global, expr_ty_adjusted(bcx, expr));
+                        return bcx;
+                    },
+                    Err(consts::ConstEvalFailure::Runtime(_)) => {
+                        // in case const evaluation errors, translate normally
+                        // debug assertions catch the same errors
+                        // see RFC 1229
+                    },
+                    Err(consts::ConstEvalFailure::Compiletime(_)) => {
+                        return bcx;
+                    },
+                }
             }
             // Even if we don't have a value to emit, and the expression
             // doesn't have any side-effects, we still have to translate the
@@ -221,48 +233,64 @@ pub fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         check_const::ConstQualif::NOT_CONST |
         check_const::ConstQualif::NEEDS_DROP
     ) {
-        let global = consts::get_const_expr_as_global(bcx.ccx(), expr, qualif,
-                                                      bcx.fcx.param_substs);
+        match consts::get_const_expr_as_global(bcx.ccx(), expr, qualif,
+                                                            bcx.fcx.param_substs,
+                                                            consts::TrueConst::No) {
+            Ok(global) => {
+                if qualif.intersects(check_const::ConstQualif::HAS_STATIC_BORROWS) {
+                    // Is borrowed as 'static, must return lvalue.
+
+                    // Cast pointer to global, because constants have different types.
+                    let const_ty = expr_ty_adjusted(bcx, expr);
+                    let llty = type_of::type_of(bcx.ccx(), const_ty);
+                    let global = PointerCast(bcx, global, llty.ptr_to());
+                    let datum = Datum::new(global, const_ty, Lvalue::new("expr::trans"));
+                    return DatumBlock::new(bcx, datum.to_expr_datum());
+                }
 
-        if qualif.intersects(check_const::ConstQualif::HAS_STATIC_BORROWS) {
-            // Is borrowed as 'static, must return lvalue.
+                // Otherwise, keep around and perform adjustments, if needed.
+                let const_ty = if adjusted_global {
+                    expr_ty_adjusted(bcx, expr)
+                } else {
+                    expr_ty(bcx, expr)
+                };
 
-            // Cast pointer to global, because constants have different types.
-            let const_ty = expr_ty_adjusted(bcx, expr);
-            let llty = type_of::type_of(bcx.ccx(), const_ty);
-            let global = PointerCast(bcx, global, llty.ptr_to());
-            let datum = Datum::new(global, const_ty, Lvalue::new("expr::trans"));
-            return DatumBlock::new(bcx, datum.to_expr_datum());
+                // This could use a better heuristic.
+                Some(if type_is_immediate(bcx.ccx(), const_ty) {
+                    // Cast pointer to global, because constants have different types.
+                    let llty = type_of::type_of(bcx.ccx(), const_ty);
+                    let global = PointerCast(bcx, global, llty.ptr_to());
+                    // Maybe just get the value directly, instead of loading it?
+                    immediate_rvalue(load_ty(bcx, global, const_ty), const_ty)
+                } else {
+                    let scratch = alloc_ty(bcx, const_ty, "const");
+                    call_lifetime_start(bcx, scratch);
+                    let lldest = if !const_ty.is_structural() {
+                        // Cast pointer to slot, because constants have different types.
+                        PointerCast(bcx, scratch, val_ty(global))
+                    } else {
+                        // In this case, memcpy_ty calls llvm.memcpy after casting both
+                        // source and destination to i8*, so we don't need any casts.
+                        scratch
+                    };
+                    memcpy_ty(bcx, lldest, global, const_ty);
+                    Datum::new(scratch, const_ty, Rvalue::new(ByRef))
+                })
+            },
+            Err(consts::ConstEvalFailure::Runtime(_)) => {
+                // in case const evaluation errors, translate normally
+                // debug assertions catch the same errors
+                // see RFC 1229
+                None
+            },
+            Err(consts::ConstEvalFailure::Compiletime(_)) => {
+                // generate a dummy llvm value
+                let const_ty = expr_ty(bcx, expr);
+                let llty = type_of::type_of(bcx.ccx(), const_ty);
+                let dummy = C_undef(llty.ptr_to());
+                Some(Datum::new(dummy, const_ty, Rvalue::new(ByRef)))
+            },
         }
-
-        // Otherwise, keep around and perform adjustments, if needed.
-        let const_ty = if adjusted_global {
-            expr_ty_adjusted(bcx, expr)
-        } else {
-            expr_ty(bcx, expr)
-        };
-
-        // This could use a better heuristic.
-        Some(if type_is_immediate(bcx.ccx(), const_ty) {
-            // Cast pointer to global, because constants have different types.
-            let llty = type_of::type_of(bcx.ccx(), const_ty);
-            let global = PointerCast(bcx, global, llty.ptr_to());
-            // Maybe just get the value directly, instead of loading it?
-            immediate_rvalue(load_ty(bcx, global, const_ty), const_ty)
-        } else {
-            let scratch = alloc_ty(bcx, const_ty, "const");
-            call_lifetime_start(bcx, scratch);
-            let lldest = if !const_ty.is_structural() {
-                // Cast pointer to slot, because constants have different types.
-                PointerCast(bcx, scratch, val_ty(global))
-            } else {
-                // In this case, memcpy_ty calls llvm.memcpy after casting both
-                // source and destination to i8*, so we don't need any casts.
-                scratch
-            };
-            memcpy_ty(bcx, lldest, global, const_ty);
-            Datum::new(scratch, const_ty, Rvalue::new(ByRef))
-        })
     } else {
         None
     };
@@ -334,6 +362,37 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
     }
 }
 
+fn adjustment_required<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                   expr: &hir::Expr) -> bool {
+    let adjustment = match bcx.tcx().tables.borrow().adjustments.get(&expr.id).cloned() {
+        None => { return false; }
+        Some(adj) => adj
+    };
+
+    // Don't skip a conversion from Box<T> to &T, etc.
+    if bcx.tcx().is_overloaded_autoderef(expr.id, 0) {
+        return true;
+    }
+
+    match adjustment {
+        AdjustReifyFnPointer => {
+            // FIXME(#19925) once fn item types are
+            // zero-sized, we'll need to return true here
+            false
+        }
+        AdjustUnsafeFnPointer => {
+            // purely a type-level thing
+            false
+        }
+        AdjustDerefRef(ref adj) => {
+            // We are a bit paranoid about adjustments and thus might have a re-
+            // borrow here which merely derefs and then refs again (it might have
+            // a different region or mutability, but we don't care here).
+            !(adj.autoderefs == 1 && adj.autoref.is_some() && adj.unsize.is_none())
+        }
+    }
+}
+
 /// Helper for trans that apply adjustments from `expr` to `datum`, which should be the unadjusted
 /// translation of `expr`.
 fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
@@ -533,7 +592,7 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                               Rvalue::new(ByRef)));
                 } else {
                     // Otherwise, simply copy the data from the source.
-                    assert_eq!(src_ty, target_ty);
+                    assert!(src_ty.is_phantom_data() || src_ty == target_ty);
                     memcpy_ty(bcx, ll_target, ll_source, src_ty);
                 }
             }
@@ -630,14 +689,11 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let _icx = push_ctxt("trans_datum_unadjusted");
 
     match expr.node {
-        hir::ExprParen(ref e) => {
-            trans(bcx, &**e)
-        }
         hir::ExprPath(..) => {
             trans_def(bcx, expr, bcx.def(expr.id))
         }
-        hir::ExprField(ref base, ident) => {
-            trans_rec_field(bcx, &**base, ident.node.name)
+        hir::ExprField(ref base, name) => {
+            trans_rec_field(bcx, &**base, name.node)
         }
         hir::ExprTupField(ref base, idx) => {
             trans_rec_tup_field(bcx, &**base, idx.node)
@@ -645,7 +701,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         hir::ExprIndex(ref base, ref idx) => {
             trans_index(bcx, expr, &**base, &**idx, MethodCall::expr(expr.id))
         }
-        hir::ExprBox(_, ref contents) => {
+        hir::ExprBox(ref contents) => {
             // Special case for `Box<T>`
             let box_ty = expr_ty(bcx, expr);
             let contents_ty = expr_ty(bcx, &**contents);
@@ -895,13 +951,13 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let const_ty = expr_ty(bcx, ref_expr);
 
             // For external constants, we don't inline.
-            let val = if did.is_local() {
+            let val = if let Some(node_id) = bcx.tcx().map.as_local_node_id(did) {
                 // Case 1.
 
                 // 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 val = base::get_item_val(bcx.ccx(), node_id);
                 let pty = type_of::type_of(bcx.ccx(), const_ty).ptr_to();
                 PointerCast(bcx, val, pty)
             } else {
@@ -934,14 +990,11 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
 
     match expr.node {
-        hir::ExprParen(ref e) => {
-            trans_into(bcx, &**e, Ignore)
-        }
         hir::ExprBreak(label_opt) => {
-            controlflow::trans_break(bcx, expr, label_opt.map(|l| l.node))
+            controlflow::trans_break(bcx, expr, label_opt.map(|l| l.node.name))
         }
         hir::ExprAgain(label_opt) => {
-            controlflow::trans_cont(bcx, expr, label_opt.map(|l| l.node))
+            controlflow::trans_cont(bcx, expr, label_opt.map(|l| l.node.name))
         }
         hir::ExprRet(ref ex) => {
             // Check to see if the return expression itself is reachable.
@@ -1024,7 +1077,20 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
         }
         hir::ExprAssignOp(op, ref dst, ref src) => {
-            trans_assign_op(bcx, expr, op, &**dst, &**src)
+            let has_method_map = bcx.tcx()
+                                    .tables
+                                    .borrow()
+                                    .method_map
+                                    .contains_key(&MethodCall::expr(expr.id));
+
+            if has_method_map {
+                let dst = unpack_datum!(bcx, trans(bcx, &**dst));
+                let src_datum = unpack_datum!(bcx, trans(bcx, &**src));
+                trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id), dst,
+                                    Some((src_datum, src.id)), None, false).bcx
+            } else {
+                trans_assign_op(bcx, expr, op, &**dst, &**src)
+            }
         }
         hir::ExprInlineAsm(ref a) => {
             asm::trans_inline_asm(bcx, a)
@@ -1050,9 +1116,6 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
 
     match expr.node {
-        hir::ExprParen(ref e) => {
-            trans_into(bcx, &**e, dest)
-        }
         hir::ExprPath(..) => {
             trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest)
         }
@@ -1079,7 +1142,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             // trans. Shudder.
             fn make_field(field_name: &str, expr: P<hir::Expr>) -> hir::Field {
                 hir::Field {
-                    ident: codemap::dummy_spanned(token::str_to_ident(field_name)),
+                    name: codemap::dummy_spanned(token::intern(field_name)),
                     expr: expr,
                     span: codemap::DUMMY_SP,
                 }
@@ -1140,7 +1203,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
         hir::ExprLit(ref lit) => {
             match lit.node {
-                hir::LitStr(ref s, _) => {
+                ast::LitStr(ref s, _) => {
                     tvec::trans_lit_str(bcx, expr, (*s).clone(), dest)
                 }
                 _ => {
@@ -1160,14 +1223,23 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 SaveIn(lldest) => closure::Dest::SaveIn(bcx, lldest),
                 Ignore => closure::Dest::Ignore(bcx.ccx())
             };
-            let substs = match expr_ty(bcx, expr).sty {
-                ty::TyClosure(_, ref substs) => substs,
+
+            // NB. To get the id of the closure, we don't use
+            // `local_def_id(id)`, but rather we extract the closure
+            // def-id from the expr's type. This is because this may
+            // be an inlined expression from another crate, and we
+            // want to get the ORIGINAL closure def-id, since that is
+            // the key we need to find the closure-kind and
+            // closure-type etc.
+            let (def_id, substs) = match expr_ty(bcx, expr).sty {
+                ty::TyClosure(def_id, ref substs) => (def_id, substs),
                 ref t =>
                     bcx.tcx().sess.span_bug(
                         expr.span,
                         &format!("closure expr without closure type: {:?}", t)),
             };
-            closure::trans_closure_expr(dest, decl, body, expr.id, substs).unwrap_or(bcx)
+
+            closure::trans_closure_expr(dest, decl, body, expr.id, def_id, substs).unwrap_or(bcx)
         }
         hir::ExprCall(ref f, ref args) => {
             if bcx.tcx().is_method_call(expr.id) {
@@ -1216,8 +1288,11 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             // Trait casts used to come this way, now they should be coercions.
             bcx.tcx().sess.span_bug(expr.span, "DPS expr_cast (residual trait cast?)")
         }
-        hir::ExprAssignOp(op, ref dst, ref src) => {
-            trans_assign_op(bcx, expr, op, &**dst, &**src)
+        hir::ExprAssignOp(op, _, _) => {
+            bcx.tcx().sess.span_bug(
+                expr.span,
+                &format!("augmented assignment `{}=` should always be a rvalue_stmt",
+                         rustc_front::util::binop_to_string(op.node)))
         }
         _ => {
             bcx.tcx().sess.span_bug(
@@ -1320,7 +1395,7 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let _icx = push_ctxt("trans_local_var");
 
     match def {
-        def::DefUpvar(nid, _, _) => {
+        def::DefUpvar(_, nid, _, _) => {
             // Can't move upvars, so this is never a ZeroMemLastUse.
             let local_ty = node_id_type(bcx, nid);
             let lval = Lvalue::new_with_hint("expr::trans_local_var (upvar)",
@@ -1334,7 +1409,7 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 }
             }
         }
-        def::DefLocal(nid) => {
+        def::DefLocal(_, nid) => {
             let datum = match bcx.fcx.lllocals.borrow().get(&nid) {
                 Some(&v) => v,
                 None => {
@@ -1370,7 +1445,7 @@ fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let mut need_base = vec![true; vinfo.fields.len()];
 
     let numbered_fields = fields.iter().map(|field| {
-        let pos = vinfo.field_index(field.ident.node.name);
+        let pos = vinfo.field_index(field.name.node);
         need_base[pos] = false;
         (pos, &*field.expr)
     }).collect::<Vec<_>>();
@@ -1549,7 +1624,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 
 fn trans_immediate_lit<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                    expr: &hir::Expr,
-                                   lit: &hir::Lit)
+                                   lit: &ast::Lit)
                                    -> DatumBlock<'blk, 'tcx, Expr> {
     // must not be a string constant, that is a RvalueDpsExpr
     let _icx = push_ctxt("trans_immediate_lit");
@@ -1611,9 +1686,6 @@ fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             };
             immediate_rvalue_bcx(bcx, llneg, un_ty).to_expr_datumblock()
         }
-        hir::UnUniq => {
-            trans_uniq_expr(bcx, expr, un_ty, sub_expr, expr_ty(bcx, sub_expr))
-        }
         hir::UnDeref => {
             let datum = unpack_datum!(bcx, trans(bcx, sub_expr));
             deref_once(bcx, expr, datum, method_call)
@@ -1656,16 +1728,6 @@ fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     immediate_rvalue_bcx(bcx, val, box_ty).to_expr_datumblock()
 }
 
-fn ref_fat_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                           lval: Datum<'tcx, Lvalue>)
-                           -> DatumBlock<'blk, 'tcx, Expr> {
-    let dest_ty = bcx.tcx().mk_imm_ref(bcx.tcx().mk_region(ty::ReStatic), lval.ty);
-    let scratch = rvalue_scratch_datum(bcx, dest_ty, "__fat_ptr");
-    memcpy_ty(bcx, scratch.val, lval.val, scratch.ty);
-
-    DatumBlock::new(bcx, scratch.to_expr_datum())
-}
-
 fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                              expr: &hir::Expr,
                              subexpr: &hir::Expr)
@@ -1673,12 +1735,13 @@ fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let _icx = push_ctxt("trans_addr_of");
     let mut bcx = bcx;
     let sub_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, subexpr, "addr_of"));
+    let ty = expr_ty(bcx, expr);
     if !type_is_sized(bcx.tcx(), sub_datum.ty) {
-        // DST lvalue, close to a fat pointer
-        ref_fat_ptr(bcx, sub_datum)
+        // Always generate an lvalue datum, because this pointer doesn't own
+        // the data and cleanup is scheduled elsewhere.
+        DatumBlock::new(bcx, Datum::new(sub_datum.val, ty, LvalueExpr(sub_datum.kind)))
     } else {
         // Sized value, ref to a thin pointer
-        let ty = expr_ty(bcx, expr);
         immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock()
     }
 }
@@ -2381,8 +2444,8 @@ impl OverflowOpViaIntrinsic {
         bcx.ccx().get_intrinsic(&name)
     }
     fn to_intrinsic_name(&self, tcx: &ty::ctxt, ty: Ty) -> &'static str {
-        use rustc_front::hir::IntTy::*;
-        use rustc_front::hir::UintTy::*;
+        use syntax::ast::IntTy::*;
+        use syntax::ast::UintTy::*;
         use middle::ty::{TyInt, TyUint};
 
         let new_sty = match ty.sty {
@@ -2491,7 +2554,7 @@ impl OverflowOpViaInputCheck {
         // Note that the mask's value is derived from the LHS type
         // (since that is where the 32/64 distinction is relevant) but
         // the mask's type must match the RHS type (since they will
-        // both be fed into a and-binop)
+        // both be fed into an and-binop)
         let invert_mask = shift_mask_val(bcx, lhs_llty, rhs_llty, true);
 
         let outer_bits = And(bcx, rhs, invert_mask, binop_debug_loc);
@@ -2714,7 +2777,7 @@ fn expr_kind(tcx: &ty::ctxt, expr: &hir::Expr) -> ExprKind {
             ExprKind::RvalueDps
         }
 
-        hir::ExprLit(ref lit) if rustc_front::util::lit_is_str(&**lit) => {
+        hir::ExprLit(ref lit) if ast_util::lit_is_str(&**lit) => {
             ExprKind::RvalueDps
         }
 
@@ -2731,26 +2794,11 @@ fn expr_kind(tcx: &ty::ctxt, expr: &hir::Expr) -> ExprKind {
 
         hir::ExprLit(_) | // Note: LitStr is carved out above
         hir::ExprUnary(..) |
-        hir::ExprBox(None, _) |
+        hir::ExprBox(_) |
         hir::ExprAddrOf(..) |
         hir::ExprBinary(..) |
         hir::ExprCast(..) => {
             ExprKind::RvalueDatum
         }
-
-        hir::ExprBox(Some(ref place), _) => {
-            // Special case `Box<T>` for now:
-            let def_id = match tcx.def_map.borrow().get(&place.id) {
-                Some(def) => def.def_id(),
-                None => panic!("no def for place"),
-            };
-            if tcx.lang_items.exchange_heap() == Some(def_id) {
-                ExprKind::RvalueDatum
-            } else {
-                ExprKind::RvalueDps
-            }
-        }
-
-        hir::ExprParen(ref e) => expr_kind(tcx, &**e),
     }
 }
index cbb092aa4eb33b3ada7e399e4a1e2b3faaf451d9..95e9e8581bd614b22c3b643c1834165931404ab2 100644 (file)
@@ -27,20 +27,21 @@ use trans::monomorphize;
 use trans::type_::Type;
 use trans::type_of::*;
 use trans::type_of;
+use middle::infer;
 use middle::ty::{self, Ty};
 use middle::subst::Substs;
-use rustc::front::map as hir_map;
 
 use std::cmp;
+use std::iter::once;
 use libc::c_uint;
 use syntax::abi::{Cdecl, Aapcs, C, Win64, Abi};
 use syntax::abi::{PlatformIntrinsic, RustIntrinsic, Rust, RustCall, Stdcall, Fastcall, System};
+use syntax::attr;
 use syntax::codemap::Span;
 use syntax::parse::token::{InternedString, special_idents};
 use syntax::ast;
 
 use rustc_front::print::pprust;
-use rustc_front::attr;
 use rustc_front::hir;
 
 ///////////////////////////////////////////////////////////////////////////
@@ -188,7 +189,7 @@ pub fn get_extern_fn(ccx: &CrateContext,
 pub fn register_foreign_item_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                           abi: Abi, fty: Ty<'tcx>,
                                           name: &str,
-                                          attrs: &[hir::Attribute])-> ValueRef {
+                                          attrs: &[ast::Attribute])-> ValueRef {
     debug!("register_foreign_item_fn(abi={:?}, \
             ty={:?}, \
             name={})",
@@ -254,6 +255,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         _ => ccx.sess().bug("trans_native_call called on non-function type")
     };
     let fn_sig = ccx.tcx().erase_late_bound_regions(fn_sig);
+    let fn_sig = infer::normalize_associated_type(ccx.tcx(), &fn_sig);
     let llsig = foreign_signature(ccx, &fn_sig, &passed_arg_tys[..]);
     let fn_type = cabi::compute_abi_info(ccx,
                                          &llsig.llarg_tys,
@@ -558,8 +560,6 @@ pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext,
                                          -> ValueRef {
     let _icx = push_ctxt("foreign::register_foreign_fn");
 
-    let tys = foreign_types_for_id(ccx, node_id);
-    let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
     let t = ccx.tcx().node_id_to_type(node_id);
     let cconv = match t.sty {
         ty::TyBareFn(_, ref fn_ty) => {
@@ -567,6 +567,8 @@ pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext,
         }
         _ => panic!("expected bare fn in register_rust_fn_with_foreign_abi")
     };
+    let tys = foreign_types_for_fn_ty(ccx, t);
+    let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
     let llfn = base::register_fn_llvmty(ccx, sp, sym, node_id, cconv, llfn_ty);
     add_argument_attributes(&tys, llfn);
     debug!("register_rust_fn_with_foreign_abi(node_id={}, llfn_ty={}, llfn={})",
@@ -577,7 +579,7 @@ pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext,
 pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                                 decl: &hir::FnDecl,
                                                 body: &hir::Block,
-                                                attrs: &[hir::Attribute],
+                                                attrs: &[ast::Attribute],
                                                 llwrapfn: ValueRef,
                                                 param_substs: &'tcx Substs<'tcx>,
                                                 id: ast::NodeId,
@@ -600,7 +602,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                decl: &hir::FnDecl,
                                body: &hir::Block,
                                param_substs: &'tcx Substs<'tcx>,
-                               attrs: &[hir::Attribute],
+                               attrs: &[ast::Attribute],
                                id: ast::NodeId,
                                hash: Option<&str>)
                                -> ValueRef
@@ -610,10 +612,12 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         let t = tcx.node_id_to_type(id);
         let t = monomorphize::apply_param_substs(tcx, param_substs, &t);
 
-        let ps = ccx.tcx().map.with_path(id, |path| {
-            let abi = Some(hir_map::PathName(special_idents::clownshoe_abi.name));
-            link::mangle(path.chain(abi), hash)
-        });
+        let path =
+            tcx.map.def_path_from_id(id)
+                   .into_iter()
+                   .map(|e| e.data.as_interned_str())
+                   .chain(once(special_idents::clownshoe_abi.name.as_str()));
+        let ps = link::mangle(path, hash);
 
         // Compute the type that the function would have if it were just a
         // normal Rust function. This will be the type of the wrappee fn.
@@ -908,7 +912,7 @@ pub fn link_name(i: &hir::ForeignItem) -> InternedString {
         Some(ln) => ln.clone(),
         None => match weak_lang_items::link_name(&i.attrs) {
             Some(name) => name,
-            None => i.ident.name.as_str(),
+            None => i.name.as_str(),
         }
     }
 }
@@ -935,11 +939,6 @@ fn foreign_signature<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     }
 }
 
-fn foreign_types_for_id<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                  id: ast::NodeId) -> ForeignTypes<'tcx> {
-    foreign_types_for_fn_ty(ccx, ccx.tcx().node_id_to_type(id))
-}
-
 fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                      ty: Ty<'tcx>) -> ForeignTypes<'tcx> {
     let fn_sig = match ty.sty {
@@ -947,6 +946,7 @@ fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         _ => ccx.sess().bug("foreign_types_for_fn_ty called on non-function type")
     };
     let fn_sig = ccx.tcx().erase_late_bound_regions(fn_sig);
+    let fn_sig = infer::normalize_associated_type(ccx.tcx(), &fn_sig);
     let llsig = foreign_signature(ccx, &fn_sig, &fn_sig.inputs);
     let fn_ty = cabi::compute_abi_info(ccx,
                                        &llsig.llarg_tys,
index 40a290a27150e5214f85cd35a23df538a7bf39f9..d7b6cb41a0a756571f3e6ebc14dbe388396bc0de 100644 (file)
@@ -203,9 +203,9 @@ pub enum DropGlueKind<'tcx> {
     /// Skips the dtor, if any, for ty; drops the contents directly.
     /// Note that the dtor is only skipped at the most *shallow*
     /// level, namely, an `impl Drop for Ty` itself. So, for example,
-    /// if Ty is Newtype(S) then only the Drop impl for for Newtype
-    /// itself will be skipped, while the Drop impl for S, if any,
-    /// will be invoked.
+    /// if Ty is Newtype(S) then only the Drop impl for Newtype itself
+    /// will be skipped, while the Drop impl for S, if any, will be
+    /// invoked.
     TyContents(Ty<'tcx>),
 }
 
index 22d624be6fcc87151459733720e8c782f3759f06..14e1ca7675f790f9981089818017478ff4a362eb 100644 (file)
@@ -30,7 +30,8 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId)
             // Already inline
             debug!("instantiate_inline({}): already inline as node id {}",
                    ccx.tcx().item_path_str(fn_id), node_id);
-            return Some(DefId::local(node_id));
+            let node_def_id = ccx.tcx().map.local_def_id(node_id);
+            return Some(node_def_id);
         }
         Some(&None) => {
             return None; // Not inlinable
@@ -43,7 +44,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId)
     let csearch_result =
         csearch::maybe_get_item_ast(
             ccx.tcx(), fn_id,
-            Box::new(|a,b,c,d| astencode::decode_inlined_item(a, b, c, d)));
+            Box::new(astencode::decode_inlined_item));
 
     let inline_id = match csearch_result {
         csearch::FoundAst::NotFound => {
@@ -109,18 +110,17 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId)
                     let ty_vs = &ccx.tcx().lookup_adt_def(parent_id).variants;
                     assert_eq!(ast_vs.len(), ty_vs.len());
                     for (ast_v, ty_v) in ast_vs.iter().zip(ty_vs.iter()) {
-                        if ty_v.did == fn_id { my_id = ast_v.node.id; }
-                        ccx.external().borrow_mut().insert(ty_v.did, Some(ast_v.node.id));
+                        if ty_v.did == fn_id { my_id = ast_v.node.data.id(); }
+                        ccx.external().borrow_mut().insert(ty_v.did, Some(ast_v.node.data.id()));
                     }
                 }
                 hir::ItemStruct(ref struct_def, _) => {
-                    match struct_def.ctor_id {
-                        None => ccx.sess().bug("instantiate_inline: called on a \
-                                                non-tuple struct"),
-                        Some(ctor_id) => {
-                            ccx.external().borrow_mut().insert(fn_id, Some(ctor_id));
-                            my_id = ctor_id;
-                        }
+                    if struct_def.is_struct() {
+                        ccx.sess().bug("instantiate_inline: called on a \
+                                                                 non-tuple struct")
+                    } else {
+                        ccx.external().borrow_mut().insert(fn_id, Some(struct_def.id()));
+                        my_id = struct_def.id();
                     }
                 }
                 _ => ccx.sess().bug("instantiate_inline: item has a \
@@ -144,8 +144,9 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId)
             // reuse that code, it needs to be able to look up the traits for
             // inlined items.
             let ty_trait_item = ccx.tcx().impl_or_trait_item(fn_id).clone();
+            let trait_item_def_id = ccx.tcx().map.local_def_id(trait_item.id);
             ccx.tcx().impl_or_trait_items.borrow_mut()
-                     .insert(DefId::local(trait_item.id), ty_trait_item);
+                     .insert(trait_item_def_id, ty_trait_item);
 
             // If this is a default method, we can't look up the
             // impl type. But we aren't going to translate anyways, so
@@ -185,12 +186,13 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId)
         }
     };
 
-    Some(DefId::local(inline_id))
+    let inline_def_id = ccx.tcx().map.local_def_id(inline_id);
+    Some(inline_def_id)
 }
 
 pub fn get_local_instance(ccx: &CrateContext, fn_id: DefId)
     -> Option<DefId> {
-    if fn_id.is_local() {
+    if let Some(_) = ccx.tcx().map.as_local_node_id(fn_id) {
         Some(fn_id)
     } else {
         instantiate_inline(ccx, fn_id)
index bcfd44d8835d7605d257db184fcc2295367b7e9a..a8d85ae17e2bb36bb926d35dffa319784f6219eb 100644 (file)
@@ -44,10 +44,13 @@ use syntax::ast;
 use syntax::ptr::P;
 use syntax::parse::token;
 
+use rustc::session::Session;
+use syntax::codemap::Span;
+
 use std::cmp::Ordering;
 
 pub fn get_simple_intrinsic(ccx: &CrateContext, item: &hir::ForeignItem) -> Option<ValueRef> {
-    let name = match &*item.ident.name.as_str() {
+    let name = match &*item.name.as_str() {
         "sqrtf32" => "llvm.sqrt.f32",
         "sqrtf64" => "llvm.sqrt.f64",
         "powif32" => "llvm.powi.f32",
@@ -99,6 +102,10 @@ pub fn get_simple_intrinsic(ccx: &CrateContext, item: &hir::ForeignItem) -> Opti
     Some(ccx.get_intrinsic(&name))
 }
 
+pub fn span_transmute_size_error(a: &Session, b: Span, msg: &str) {
+    span_err!(a, b, E0512, "{}", msg);
+}
+
 /// Performs late verification that intrinsics are used correctly. At present,
 /// the only intrinsic that needs such verification is `transmute`.
 pub fn check_intrinsics(ccx: &CrateContext) {
@@ -127,9 +134,8 @@ pub fn check_intrinsics(ccx: &CrateContext) {
             last_failing_id = Some(transmute_restriction.id);
 
             if transmute_restriction.original_from != transmute_restriction.substituted_from {
-                ccx.sess().span_err(
-                    transmute_restriction.span,
-                    &format!("transmute called on types with potentially different sizes: \
+                span_transmute_size_error(ccx.sess(), transmute_restriction.span,
+                    &format!("transmute called with differently sized types: \
                               {} (could be {} bit{}) to {} (could be {} bit{})",
                              transmute_restriction.original_from,
                              from_type_size as usize,
@@ -138,9 +144,8 @@ pub fn check_intrinsics(ccx: &CrateContext) {
                              to_type_size as usize,
                              if to_type_size == 1 {""} else {"s"}));
             } else {
-                ccx.sess().span_err(
-                    transmute_restriction.span,
-                    &format!("transmute called on types with different sizes: \
+                span_transmute_size_error(ccx.sess(), transmute_restriction.span,
+                    &format!("transmute called with differently sized types: \
                               {} ({} bit{}) to {} ({} bit{})",
                              transmute_restriction.original_from,
                              from_type_size as usize,
@@ -180,7 +185,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         _ => panic!("expected bare_fn in trans_intrinsic_call")
     };
     let foreign_item = tcx.map.expect_foreign_item(node);
-    let name = foreign_item.ident.name.as_str();
+    let name = foreign_item.name.as_str();
 
     // For `transmute` we can just trans the input expr directly into dest
     if name == "transmute" {
@@ -798,9 +803,9 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 
         (_, "return_address") => {
             if !fcx.caller_expects_out_pointer {
-                tcx.sess.span_err(call_info.span,
-                                  "invalid use of `return_address` intrinsic: function \
-                                   does not use out pointer");
+                span_err!(tcx.sess, call_info.span, E0510,
+                          "invalid use of `return_address` intrinsic: function \
+                           does not use out pointer");
                 C_null(Type::i8p(ccx))
             } else {
                 PointerCast(bcx, llvm::get_param(fcx.llfn, 0), Type::i8p(ccx))
@@ -926,7 +931,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         (_, _) => {
             let intr = match Intrinsic::find(tcx, &name) {
                 Some(intr) => intr,
-                None => ccx.sess().span_bug(foreign_item.span, "unknown intrinsic"),
+                None => ccx.sess().span_bug(foreign_item.span,
+                                            &format!("unknown intrinsic '{}'", name)),
             };
             fn one<T>(x: Vec<T>) -> T {
                 assert_eq!(x.len(), 1);
@@ -1215,8 +1221,8 @@ fn try_intrinsic<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 // MSVC's definition of the `rust_try` function. The exact implementation here
 // is a little different than the GNU (standard) version below, not only because
 // of the personality function but also because of the other fiddly bits about
-// SEH. LLVM also currently requires us to structure this a very particular way
-// as explained below.
+// SEH. LLVM also currently requires us to structure this in a very particular
+// way as explained below.
 //
 // Like with the GNU version we generate a shim wrapper
 fn trans_msvc_try<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
@@ -1439,6 +1445,10 @@ fn get_rust_try_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
     return rust_try
 }
 
+fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
+    span_err!(a, b, E0511, "{}", c);
+}
+
 fn generic_simd_intrinsic<'blk, 'tcx, 'a>
     (bcx: Block<'blk, 'tcx>,
      name: &str,
@@ -1457,10 +1467,11 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
             emit_error!($msg, )
         };
         ($msg: tt, $($fmt: tt)*) => {
-            bcx.sess().span_err(call_info.span,
-                                &format!(concat!("invalid monomorphization of `{}` intrinsic: ",
-                                                 $msg),
-                                         name, $($fmt)*));
+            span_invalid_monomorphization_error(
+                bcx.sess(), call_info.span,
+                &format!(concat!("invalid monomorphization of `{}` intrinsic: ",
+                                 $msg),
+                         name, $($fmt)*));
         }
     }
     macro_rules! require {
@@ -1552,7 +1563,16 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
             None => bcx.sess().span_bug(call_info.span,
                                         "intrinsic call with unexpected argument shape"),
         };
-        let vector = consts::const_expr(bcx.ccx(), vector, tcx.mk_substs(substs), None).0;
+        let vector = match consts::const_expr(
+            bcx.ccx(),
+            vector,
+            tcx.mk_substs(substs),
+            None,
+            consts::TrueConst::Yes, // this should probably help simd error reporting
+        ) {
+            Ok((vector, _)) => vector,
+            Err(err) => bcx.sess().span_fatal(call_info.span, &err.description()),
+        };
 
         let indices: Option<Vec<_>> = (0..n)
             .map(|i| {
index 4b36734c67fdfaf094bf9444716772d5539a4ac2..2b711be5b07cd989a97fd59725a9e7831a55ac56 100644 (file)
@@ -38,10 +38,10 @@ use middle::ty::{self, Ty, HasTypeFlags};
 use middle::ty::MethodCall;
 
 use syntax::ast;
+use syntax::attr;
 use syntax::codemap::DUMMY_SP;
 use syntax::ptr::P;
 
-use rustc_front::attr;
 use rustc_front::visit;
 use rustc_front::hir;
 
@@ -53,7 +53,7 @@ const VTABLE_OFFSET: usize = 3;
 /// be generated once they are invoked with specific type parameters,
 /// see `trans::base::lval_static_fn()` or `trans::base::monomorphic_fn()`.
 pub fn trans_impl(ccx: &CrateContext,
-                  name: ast::Ident,
+                  name: ast::Name,
                   impl_items: &[P<hir::ImplItem>],
                   generics: &hir::Generics,
                   id: ast::NodeId) {
@@ -250,10 +250,10 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                                      impl_self,
                                                      rcvr_method));
 
-            let mth_id = method_with_name(ccx, impl_did, mname);
-            trans_fn_ref_with_substs(ccx, mth_id, ExprId(expr_id),
+            let mth = tcx.get_impl_method(impl_did, callee_substs, mname);
+            trans_fn_ref_with_substs(ccx, mth.method.def_id, ExprId(expr_id),
                                      param_substs,
-                                     callee_substs)
+                                     mth.substs)
         }
         traits::VtableObject(ref data) => {
             let idx = traits::get_vtable_index_of_object_method(tcx, data, method_id);
@@ -269,28 +269,6 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     }
 }
 
-fn method_with_name(ccx: &CrateContext, impl_id: DefId, name: ast::Name)
-                    -> DefId {
-    match ccx.impl_method_cache().borrow().get(&(impl_id, name)).cloned() {
-        Some(m) => return m,
-        None => {}
-    }
-
-    let impl_items = ccx.tcx().impl_items.borrow();
-    let impl_items =
-        impl_items.get(&impl_id)
-                  .expect("could not find impl while translating");
-    let meth_did = impl_items.iter()
-                             .find(|&did| {
-                                ccx.tcx().impl_or_trait_item(did.def_id()).name() == name
-                             }).expect("could not find method while \
-                                        translating");
-
-    ccx.impl_method_cache().borrow_mut().insert((impl_id, name),
-                                              meth_did.def_id());
-    meth_did.def_id()
-}
-
 fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                           method_call: MethodCall,
                                           self_expr: Option<&hir::Expr>,
@@ -312,20 +290,19 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                         item")
                 }
             };
-            let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
-
             // create a concatenated set of substitutions which includes
             // those from the impl and those from the method:
             let callee_substs =
                 combine_impl_and_methods_tps(
                     bcx, MethodCallKey(method_call), vtable_impl.substs);
 
+            let mth = bcx.tcx().get_impl_method(impl_did, callee_substs, mname);
             // translate the function
             let datum = trans_fn_ref_with_substs(bcx.ccx(),
-                                                 mth_id,
+                                                 mth.method.def_id,
                                                  MethodCallKey(method_call),
                                                  bcx.fcx.param_substs,
-                                                 callee_substs);
+                                                 mth.substs);
 
             Callee { bcx: bcx, data: Fn(datum.val), ty: datum.ty }
         }
@@ -499,8 +476,7 @@ fn trans_trait_callee_from_llval<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 ///    }
 ///
 /// What is the value of `x` when `foo` is invoked with `T=SomeTrait`?
-/// The answer is that it it is a shim function generate by this
-/// routine:
+/// The answer is that it is a shim function generated by this routine:
 ///
 ///    fn shim(t: &SomeTrait) -> int {
 ///        // ... call t.get() virtually ...
@@ -674,7 +650,9 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         C_uint(ccx, align)
     ].into_iter().chain(methods).collect();
 
-    let vtable = consts::addr_of(ccx, C_struct(ccx, &components, false), "vtable");
+    let vtable_const = C_struct(ccx, &components, false);
+    let align = machine::llalign_of_pref(ccx, val_ty(vtable_const));
+    let vtable = consts::addr_of(ccx, vtable_const, align, "vtable");
 
     ccx.vtables().borrow_mut().insert(trait_ref, vtable);
     vtable
@@ -738,22 +716,17 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
             // The substitutions we have are on the impl, so we grab
             // the method type from the impl to substitute into.
-            let impl_method_def_id = method_with_name(ccx, impl_id, name);
-            let impl_method_type = match tcx.impl_or_trait_item(impl_method_def_id) {
-                ty::MethodTraitItem(m) => m,
-                _ => ccx.sess().bug("should be a method, not other assoc item"),
-            };
+            let mth = tcx.get_impl_method(impl_id, substs.clone(), name);
 
-            debug!("emit_vtable_methods: impl_method_type={:?}",
-                   impl_method_type);
+            debug!("emit_vtable_methods: mth={:?}", mth);
 
             // If this is a default method, it's possible that it
             // relies on where clauses that do not hold for this
             // particular set of type parameters. Note that this
             // method could then never be called, so we do not want to
             // try and trans it, in that case. Issue #23435.
-            if tcx.provided_source(impl_method_def_id).is_some() {
-                let predicates = impl_method_type.predicates.predicates.subst(tcx, &substs);
+            if mth.is_provided {
+                let predicates = mth.method.predicates.predicates.subst(tcx, &mth.substs);
                 if !normalize_and_test_predicates(ccx, predicates.into_vec()) {
                     debug!("emit_vtable_methods: predicates do not hold");
                     return nullptr;
@@ -761,10 +734,10 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             }
 
             trans_fn_ref_with_substs(ccx,
-                                     impl_method_def_id,
+                                     mth.method.def_id,
                                      ExprId(0),
                                      param_substs,
-                                     substs.clone()).val
+                                     mth.substs).val
         })
         .collect()
 }
@@ -773,7 +746,7 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 fn opaque_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, method_ty: &ty::BareFnTy<'tcx>)
                           -> &'tcx ty::BareFnTy<'tcx> {
     let mut inputs = method_ty.sig.0.inputs.clone();
-    inputs[0] = tcx.mk_mut_ptr(tcx.mk_mach_int(hir::TyI8));
+    inputs[0] = tcx.mk_mut_ptr(tcx.mk_mach_int(ast::TyI8));
 
     tcx.mk_bare_fn(ty::BareFnTy {
         unsafety: method_ty.unsafety,
index 20c3f356b1122b50676b6e6832f05c901fc01b11..1f9116f7491d16b4ece898c79418c5dc5bc337cb 100644 (file)
@@ -28,17 +28,17 @@ use middle::ty::{self, HasTypeFlags, Ty};
 use rustc::front::map as hir_map;
 
 use rustc_front::hir;
-use rustc_front::attr;
 
 use syntax::abi;
 use syntax::ast;
+use syntax::attr;
 use std::hash::{Hasher, Hash, SipHasher};
 
 pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                 fn_id: DefId,
                                 psubsts: &'tcx subst::Substs<'tcx>,
                                 ref_id: Option<ast::NodeId>)
-    -> (ValueRef, Ty<'tcx>, bool) {
+                                -> (ValueRef, Ty<'tcx>, bool) {
     debug!("monomorphic_fn(\
             fn_id={:?}, \
             real_substs={:?}, \
@@ -49,6 +49,9 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     assert!(!psubsts.types.needs_infer() && !psubsts.types.has_param_types());
 
+    // we can only monomorphize things in this crate (or inlined into it)
+    let fn_node_id = ccx.tcx().map.as_local_node_id(fn_id).unwrap();
+
     let _icx = push_ctxt("monomorphic_fn");
 
     let hash_id = MonoId {
@@ -82,7 +85,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     let map_node = session::expect(
         ccx.sess(),
-        ccx.tcx().map.find(fn_id.node),
+        ccx.tcx().map.find(fn_node_id),
         || {
             format!("while monomorphizing {:?}, couldn't find it in \
                      the item map (may have attempted to monomorphize \
@@ -91,10 +94,10 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         });
 
     if let hir_map::NodeForeignItem(_) = map_node {
-        let abi = ccx.tcx().map.get_foreign_abi(fn_id.node);
+        let abi = ccx.tcx().map.get_foreign_abi(fn_node_id);
         if abi != abi::RustIntrinsic && abi != abi::PlatformIntrinsic {
             // Foreign externs don't have to be monomorphized.
-            return (get_item_val(ccx, fn_id.node), mono_ty, true);
+            return (get_item_val(ccx, fn_node_id), mono_ty, true);
         }
     }
 
@@ -107,11 +110,13 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             Some(&d) => d, None => 0
         };
 
+        debug!("monomorphic_fn: depth for fn_id={:?} is {:?}", fn_id, depth+1);
+
         // Random cut-off -- code that needs to instantiate the same function
         // recursively more than thirty times can probably safely be assumed
         // to be causing an infinite expansion.
         if depth > ccx.sess().recursion_limit.get() {
-            ccx.sess().span_fatal(ccx.tcx().map.span(fn_id.node),
+            ccx.sess().span_fatal(ccx.tcx().map.span(fn_node_id),
                 "reached the recursion limit during monomorphization");
         }
 
@@ -125,9 +130,8 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         mono_ty.hash(&mut state);
 
         hash = format!("h{}", state.finish());
-        ccx.tcx().map.with_path(fn_id.node, |path| {
-            exported_name(path, &hash[..])
-        })
+        let path = ccx.tcx().map.def_path_from_id(fn_node_id);
+        exported_name(path, &hash[..])
     };
 
     debug!("monomorphize_fn mangled to {}", s);
@@ -136,7 +140,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let mut hash_id = Some(hash_id);
     let mut mk_lldecl = |abi: abi::Abi| {
         let lldecl = if abi != abi::Rust {
-            foreign::decl_rust_fn_with_foreign_abi(ccx, mono_ty, &s[..])
+            foreign::decl_rust_fn_with_foreign_abi(ccx, mono_ty, &s)
         } else {
             // FIXME(nagisa): perhaps needs a more fine grained selection? See
             // setup_lldecl below.
@@ -146,7 +150,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         ccx.monomorphized().borrow_mut().insert(hash_id.take().unwrap(), lldecl);
         lldecl
     };
-    let setup_lldecl = |lldecl, attrs: &[hir::Attribute]| {
+    let setup_lldecl = |lldecl, attrs: &[ast::Attribute]| {
         base::update_linkage(ccx, lldecl, None, base::OriginalTranslation);
         attributes::from_fn_attrs(ccx, attrs, lldecl);
 
@@ -178,10 +182,10 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                   if needs_body {
                       if abi != abi::Rust {
                           foreign::trans_rust_fn_with_foreign_abi(
-                              ccx, &**decl, &**body, &[], d, psubsts, fn_id.node,
+                              ccx, &**decl, &**body, &[], d, psubsts, fn_node_id,
                               Some(&hash[..]));
                       } else {
-                          trans_fn(ccx, &**decl, &**body, d, psubsts, fn_id.node, &[]);
+                          trans_fn(ccx, &**decl, &**body, d, psubsts, fn_node_id, &[]);
                       }
                   }
 
@@ -193,11 +197,11 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             }
         }
         hir_map::NodeVariant(v) => {
-            let variant = inlined_variant_def(ccx, fn_id.node);
-            assert_eq!(v.node.name.name, variant.name);
+            let variant = inlined_variant_def(ccx, fn_node_id);
+            assert_eq!(v.node.name, variant.name);
             let d = mk_lldecl(abi::Rust);
             attributes::inline(d, attributes::InlineAttr::Hint);
-            trans_enum_variant(ccx, fn_id.node, variant.disr_val, psubsts, d);
+            trans_enum_variant(ccx, fn_node_id, variant.disr_val, psubsts, d);
             d
         }
         hir_map::NodeImplItem(impl_item) => {
@@ -242,9 +246,11 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         hir_map::NodeStructCtor(struct_def) => {
             let d = mk_lldecl(abi::Rust);
             attributes::inline(d, attributes::InlineAttr::Hint);
+            if struct_def.is_struct() {
+                panic!("ast-mapped struct didn't have a ctor id")
+            }
             base::trans_tuple_struct(ccx,
-                                     struct_def.ctor_id.expect("ast-mapped tuple struct \
-                                                                didn't have a ctor id"),
+                                     struct_def.id(),
                                      psubsts,
                                      d);
             d
@@ -256,7 +262,6 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         hir_map::NodeTyParam(..) |
         hir_map::NodeExpr(..) |
         hir_map::NodeStmt(..) |
-        hir_map::NodeArg(..) |
         hir_map::NodeBlock(..) |
         hir_map::NodePat(..) |
         hir_map::NodeLocal(..) => {
index 8deaa045c84d5d50e0da5feb0bd451e027b633c4..c7e1af5853d11a48ca3b34eef95bb3cb75d3b3a6 100644 (file)
@@ -30,6 +30,7 @@ use middle::ty::{self, Ty};
 
 use rustc_front::hir;
 
+use syntax::ast;
 use syntax::parse::token::InternedString;
 
 #[derive(Copy, Clone)]
@@ -91,7 +92,7 @@ pub fn trans_slice_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     // Handle the "..." case (returns a slice since strings are always unsized):
     if let hir::ExprLit(ref lit) = content_expr.node {
-        if let hir::LitStr(ref s, _) = lit.node {
+        if let ast::LitStr(ref s, _) = lit.node {
             let scratch = rvalue_scratch_datum(bcx, vec_ty, "");
             bcx = trans_lit_str(bcx,
                                 content_expr,
@@ -172,7 +173,7 @@ fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     match content_expr.node {
         hir::ExprLit(ref lit) => {
             match lit.node {
-                hir::LitStr(ref s, _) => {
+                ast::LitStr(ref s, _) => {
                     match dest {
                         Ignore => return bcx,
                         SaveIn(lldest) => {
@@ -268,7 +269,7 @@ fn elements_required(bcx: Block, content_expr: &hir::Expr) -> usize {
     match content_expr.node {
         hir::ExprLit(ref lit) => {
             match lit.node {
-                hir::LitStr(ref s, _) => s.len(),
+                ast::LitStr(ref s, _) => s.len(),
                 _ => {
                     bcx.tcx().sess.span_bug(content_expr.span,
                                             "unexpected evec content")
index e0df6ec35c2f9febb252d249d9763b6a46126e62..c635d1ba233fd99fd8b5757647ebf8d61033d142 100644 (file)
@@ -17,7 +17,7 @@ use llvm::{Float, Double, X86_FP80, PPC_FP128, FP128};
 use trans::context::CrateContext;
 use util::nodemap::FnvHashMap;
 
-use rustc_front::hir;
+use syntax::ast;
 
 use std::ffi::CString;
 use std::mem;
@@ -125,30 +125,30 @@ impl Type {
         }
     }
 
-    pub fn int_from_ty(ccx: &CrateContext, t: hir::IntTy) -> Type {
+    pub fn int_from_ty(ccx: &CrateContext, t: ast::IntTy) -> Type {
         match t {
-            hir::TyIs => ccx.int_type(),
-            hir::TyI8 => Type::i8(ccx),
-            hir::TyI16 => Type::i16(ccx),
-            hir::TyI32 => Type::i32(ccx),
-            hir::TyI64 => Type::i64(ccx)
+            ast::TyIs => ccx.int_type(),
+            ast::TyI8 => Type::i8(ccx),
+            ast::TyI16 => Type::i16(ccx),
+            ast::TyI32 => Type::i32(ccx),
+            ast::TyI64 => Type::i64(ccx)
         }
     }
 
-    pub fn uint_from_ty(ccx: &CrateContext, t: hir::UintTy) -> Type {
+    pub fn uint_from_ty(ccx: &CrateContext, t: ast::UintTy) -> Type {
         match t {
-            hir::TyUs => ccx.int_type(),
-            hir::TyU8 => Type::i8(ccx),
-            hir::TyU16 => Type::i16(ccx),
-            hir::TyU32 => Type::i32(ccx),
-            hir::TyU64 => Type::i64(ccx)
+            ast::TyUs => ccx.int_type(),
+            ast::TyU8 => Type::i8(ccx),
+            ast::TyU16 => Type::i16(ccx),
+            ast::TyU32 => Type::i32(ccx),
+            ast::TyU64 => Type::i64(ccx)
         }
     }
 
-    pub fn float_from_ty(ccx: &CrateContext, t: hir::FloatTy) -> Type {
+    pub fn float_from_ty(ccx: &CrateContext, t: ast::FloatTy) -> Type {
         match t {
-            hir::TyF32 => Type::f32(ccx),
-            hir::TyF64 => Type::f64(ccx),
+            ast::TyF32 => Type::f32(ccx),
+            ast::TyF64 => Type::f64(ccx),
         }
     }
 
index 43e1ad8115beda7f619098fc6966fafb2fd23818..437c0d9cbc341df0ec12091e9f4edd6df911cc98 100644 (file)
@@ -21,7 +21,7 @@ use middle::ty::{self, RegionEscape, Ty};
 use trans::type_::Type;
 
 use syntax::abi;
-use rustc_front::hir;
+use syntax::ast;
 
 // LLVM doesn't like objects that are too big. Issue #17913
 fn ensure_array_fits_in_address_space<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
@@ -361,7 +361,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
           let repr = adt::represent_type(cx, t);
           // Unboxed closures can have substitutions in all spaces
           // inherited from their environment, so we use entire
-          // contents of the VecPerParamSpace to to construct the llvm
+          // contents of the VecPerParamSpace to construct the llvm
           // name
           adt::incomplete_type_of(cx, &*repr, "closure")
       }
@@ -379,7 +379,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
                   let unsized_part = cx.tcx().struct_tail(ty);
                   let info_ty = match unsized_part.sty {
                       ty::TyStr | ty::TyArray(..) | ty::TySlice(_) => {
-                          Type::uint_from_ty(cx, hir::TyUs)
+                          Type::uint_from_ty(cx, ast::TyUs)
                       }
                       ty::TyTrait(_) => Type::vtable_ptr(cx),
                       _ => panic!("Unexpected type returned from \
index 971ca329e6b5afc47cf98c1fd40e5e6b6d670754..34378445c60877e54a13c160b872ff8ecf733ca2 100644 (file)
@@ -52,7 +52,7 @@ use middle::astconv_util::{prim_ty_to_ty, prohibit_type_params, prohibit_project
 use middle::const_eval::{self, ConstVal};
 use middle::const_eval::EvalHint::UncheckedExprHint;
 use middle::def;
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::DefId;
 use middle::resolve_lifetime as rl;
 use middle::privacy::{AllPublic, LastMod};
 use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace};
@@ -66,7 +66,6 @@ use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
 use util::common::{ErrorReported, FN_OUTPUT_NAME};
 use util::nodemap::FnvHashSet;
 
-use std::slice;
 use syntax::{abi, ast};
 use syntax::codemap::{Span, Pos};
 use syntax::feature_gate::{GateIssue, emit_feature_err};
@@ -74,7 +73,7 @@ use syntax::parse::token;
 
 use rustc_front::print::pprust;
 use rustc_front::hir;
-
+use rustc_back::slice;
 
 pub trait AstConv<'tcx> {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
@@ -167,12 +166,13 @@ pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &hir::Lifetime)
         }
 
         Some(&rl::DefLateBoundRegion(debruijn, id)) => {
-            ty::ReLateBound(debruijn, ty::BrNamed(DefId::local(id), lifetime.name))
+            ty::ReLateBound(debruijn, ty::BrNamed(tcx.map.local_def_id(id), lifetime.name))
         }
 
         Some(&rl::DefEarlyBoundRegion(space, index, id)) => {
+            let def_id = tcx.map.local_def_id(id);
             ty::ReEarlyBound(ty::EarlyBoundRegion {
-                param_id: id,
+                def_id: def_id,
                 space: space,
                 index: index,
                 name: lifetime.name
@@ -182,7 +182,7 @@ pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &hir::Lifetime)
         Some(&rl::DefFreeRegion(scope, id)) => {
             ty::ReFree(ty::FreeRegion {
                     scope: tcx.region_maps.item_extent(scope.node_id),
-                    bound_region: ty::BrNamed(DefId::local(id),
+                    bound_region: ty::BrNamed(tcx.map.local_def_id(id),
                                               lifetime.name)
                 })
         }
@@ -346,7 +346,7 @@ fn create_region_substs<'tcx>(
 {
     let tcx = this.tcx();
 
-    // If the type is parameterized by the this region, then replace this
+    // If the type is parameterized by this region, then replace this
     // region with the current anon region binding (in other words,
     // whatever & would get replaced with).
     let expected_num_region_params = decl_generics.regions.len(TypeSpace);
@@ -393,7 +393,7 @@ fn create_substs_for_ast_path<'tcx>(
     let tcx = this.tcx();
 
     debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \
-           types_provided={:?}, region_substs={:?}",
+           types_provided={:?}, region_substs={:?})",
            decl_generics, self_ty, types_provided,
            region_substs);
 
@@ -474,6 +474,9 @@ fn create_substs_for_ast_path<'tcx>(
         }
     }
 
+    debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}",
+           decl_generics, self_ty, substs);
+
     substs
 }
 
@@ -545,7 +548,7 @@ fn convert_angle_bracketed_parameters<'tcx>(this: &AstConv<'tcx>,
 
     let assoc_bindings: Vec<_> =
         data.bindings.iter()
-                     .map(|b| ConvertedBinding { item_name: b.ident.name,
+                     .map(|b| ConvertedBinding { item_name: b.name,
                                                  ty: ast_ty_to_ty(this, rscope, &*b.ty),
                                                  span: b.span })
                      .collect();
@@ -741,6 +744,7 @@ fn ast_path_to_poly_trait_ref<'a,'tcx>(
     poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
     -> ty::PolyTraitRef<'tcx>
 {
+    debug!("ast_path_to_poly_trait_ref(trait_segment={:?})", trait_segment);
     // The trait reference introduces a binding level here, so
     // we need to shift the `rscope`. It'd be nice if we could
     // do away with this rscope stuff and work this knowledge
@@ -774,6 +778,8 @@ fn ast_path_to_poly_trait_ref<'a,'tcx>(
         poly_projections.extend(converted_bindings);
     }
 
+    debug!("ast_path_to_poly_trait_ref(trait_segment={:?}, projections={:?}) -> {:?}",
+           trait_segment, poly_projections, poly_trait_ref);
     poly_trait_ref
 }
 
@@ -1103,7 +1109,18 @@ fn make_object_type<'tcx>(this: &AstConv<'tcx>,
         object.principal_trait_ref_with_self_ty(tcx, tcx.types.err);
 
     // ensure the super predicates and stop if we encountered an error
-    if this.ensure_super_predicates(span, object.principal_def_id()).is_err() {
+    if this.ensure_super_predicates(span, principal.def_id()).is_err() {
+        return tcx.types.err;
+    }
+
+    // check that there are no gross object safety violations,
+    // most importantly, that the supertraits don't contain Self,
+    // to avoid ICE-s.
+    let object_safety_violations =
+        traits::astconv_object_safety_violations(tcx, principal.def_id());
+    if !object_safety_violations.is_empty() {
+        traits::report_object_safety_error(
+            tcx, span, principal.def_id(), object_safety_violations, false);
         return tcx.types.err;
     }
 
@@ -1220,7 +1237,7 @@ fn one_bound_for_assoc_type<'tcx>(tcx: &ty::ctxt<'tcx>,
     Ok(bounds[0].clone())
 }
 
-// Create a type from a path to an associated type.
+// Create a type from a path to an associated type.
 // For a path A::B::C::D, ty and ty_path_def are the type and def for A::B::C
 // and item_segment is the path segment for D. We return a type and a def for
 // the whole path.
@@ -1246,7 +1263,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
         (_, def::DefSelfTy(Some(trait_did), Some((impl_id, _)))) => {
             // `Self` in an impl of a trait - we have a concrete self type and a
             // trait reference.
-            let trait_ref = tcx.impl_trait_ref(DefId::local(impl_id)).unwrap();
+            let trait_ref = tcx.impl_trait_ref(tcx.map.local_def_id(impl_id)).unwrap();
             let trait_ref = if let Some(free_substs) = this.get_free_substs() {
                 trait_ref.subst(tcx, free_substs)
             } else {
@@ -1273,9 +1290,9 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
             }
         }
         (&ty::TyParam(_), def::DefSelfTy(Some(trait_did), None)) => {
-            assert_eq!(trait_did.krate, LOCAL_CRATE);
+            let trait_node_id = tcx.map.as_local_node_id(trait_did).unwrap();
             match find_bound_for_assoc_item(this,
-                                            trait_did.node,
+                                            trait_node_id,
                                             token::special_idents::type_self.name,
                                             assoc_name,
                                             span) {
@@ -1284,9 +1301,9 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
             }
         }
         (&ty::TyParam(_), def::DefTyParam(_, _, param_did, param_name)) => {
-            assert_eq!(param_did.krate, LOCAL_CRATE);
+            let param_node_id = tcx.map.as_local_node_id(param_did).unwrap();
             match find_bound_for_assoc_item(this,
-                                            param_did.node,
+                                            param_node_id,
                                             param_name,
                                             assoc_name,
                                             span) {
@@ -1307,15 +1324,15 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
     let trait_did = bound.0.def_id;
     let ty = this.projected_ty_from_poly_trait_ref(span, bound, assoc_name);
 
-    let item_did = if trait_did.is_local() {
+    let item_did = if let Some(trait_id) = tcx.map.as_local_node_id(trait_did) {
         // `ty::trait_items` used below requires information generated
         // by type collection, which may be in progress at this point.
-        match tcx.map.expect_item(trait_did.node).node {
+        match tcx.map.expect_item(trait_id).node {
             hir::ItemTrait(_, _, _, ref trait_items) => {
                 let item = trait_items.iter()
-                                      .find(|i| i.ident.name == assoc_name)
+                                      .find(|i| i.name == assoc_name)
                                       .expect("missing associated type");
-                DefId::local(item.id)
+                tcx.map.local_def_id(item.id)
             }
             _ => unreachable!()
         }
@@ -1489,11 +1506,12 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
             // we don't have the trait information around, which is just sad.
 
             if !base_segments.is_empty() {
+                let id_node = tcx.map.as_local_node_id(id).unwrap();
                 span_err!(tcx.sess,
                           span,
                           E0247,
                           "found module name used as a type: {}",
-                          tcx.map.node_to_string(id.node));
+                          tcx.map.node_to_user_string(id_node));
                 return this.tcx().types.err;
             }
 
@@ -1503,10 +1521,10 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
             prim_ty_to_ty(tcx, base_segments, prim_ty)
         }
         _ => {
-            let node = def.def_id().node;
+            let id_node = tcx.map.as_local_node_id(def.def_id()).unwrap();
             span_err!(tcx.sess, span, E0248,
                       "found value `{}` used as a type",
-                      tcx.map.path_to_string(node));
+                      tcx.map.path_to_string(id_node));
             return this.tcx().types.err;
         }
     }
@@ -1621,7 +1639,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
             } else if let Some(hir::QSelf { position: 0, .. }) = *maybe_qself {
                 // Create some fake resolution that can't possibly be a type.
                 def::PathResolution {
-                    base_def: def::DefMod(DefId::local(ast::CRATE_NODE_ID)),
+                    base_def: def::DefMod(tcx.map.local_def_id(ast::CRATE_NODE_ID)),
                     last_private: LastMod(AllPublic),
                     depth: path.segments.len()
                 }
@@ -1655,7 +1673,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
         }
         hir::TyFixedLengthVec(ref ty, ref e) => {
             let hint = UncheckedExprHint(tcx.types.usize);
-            match const_eval::eval_const_expr_partial(tcx, &e, hint) {
+            match const_eval::eval_const_expr_partial(tcx, &e, hint, None) {
                 Ok(r) => {
                     match r {
                         ConstVal::Int(i) =>
@@ -1673,12 +1691,10 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
                     }
                 }
                 Err(ref r) => {
-                    let subspan  =
-                        ast_ty.span.lo <= r.span.lo && r.span.hi <= ast_ty.span.hi;
                     span_err!(tcx.sess, r.span, E0250,
                               "array length constant evaluation error: {}",
                               r.description());
-                    if !subspan {
+                    if !ast_ty.span.contains(r.span) {
                         span_note!(tcx.sess, ast_ty.span, "for array length here")
                     }
                     this.tcx().types.err
@@ -1686,7 +1702,9 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
             }
         }
         hir::TyTypeof(ref _e) => {
-            tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
+            span_err!(tcx.sess, ast_ty.span, E0516,
+                  "`typeof` is a reserved keyword but unimplemented");
+            tcx.types.err
         }
         hir::TyInfer => {
             // TyInfer also appears as the type of arguments or return
index 2ce06786db281e86df0ec4d721861387010d2eb6..2e0af6a5d852a6c47be6fc33ff981bb9c33aa710 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use middle::def;
-use middle::def_id::DefId;
 use middle::infer;
 use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding};
 use middle::pat_util::pat_is_resolved_const;
@@ -26,6 +25,7 @@ use util::nodemap::FnvHashMap;
 use std::cmp;
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 use syntax::ast;
+use syntax::ext::mtwt;
 use syntax::codemap::{Span, Spanned};
 use syntax::ptr::P;
 
@@ -56,7 +56,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             // They can denote both statically and dynamically sized byte arrays
             let mut pat_ty = expr_ty;
             if let hir::ExprLit(ref lt) = lt.node {
-                if let hir::LitByteStr(_) = lt.node {
+                if let ast::LitByteStr(_) = lt.node {
                     let expected_ty = structurally_resolved_type(fcx, pat.span, expected);
                     if let ty::TyRef(_, mt) = expected_ty.sty {
                         if let ty::TySlice(_) = mt.ty.sty {
@@ -179,7 +179,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
 
             // if there are multiple arms, make sure they all agree on
             // what the type of the binding `x` ought to be
-            let canon_id = *pcx.map.get(&path.node).unwrap();
+            let canon_id = *pcx.map.get(&mtwt::resolve(path.node)).unwrap();
             if canon_id != pat.id {
                 let ct = fcx.local_ty(pat.span, canon_id);
                 demand::eqtype(fcx, pat.span, ct, typ);
@@ -202,9 +202,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             let path_res = if let Some(&d) = tcx.def_map.borrow().get(&pat.id) {
                 d
             } else if qself.position == 0 {
+                // This is just a sentinel for finish_resolving_def_to_ty.
+                let sentinel = fcx.tcx().map.local_def_id(ast::CRATE_NODE_ID);
                 def::PathResolution {
-                    // This is just a sentinel for finish_resolving_def_to_ty.
-                    base_def: def::DefMod(DefId::local(ast::CRATE_NODE_ID)),
+                    base_def: def::DefMod(sentinel),
                     last_private: LastMod(AllPublic),
                     depth: path.segments.len()
                 }
@@ -259,17 +260,30 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             }
         }
         hir::PatRegion(ref inner, mutbl) => {
-            let inner_ty = fcx.infcx().next_ty_var();
-
-            let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
-            let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
-            let rptr_ty = tcx.mk_ref(tcx.mk_region(region), mt);
-
+            let expected = fcx.infcx().shallow_resolve(expected);
             if check_dereferencable(pcx, pat.span, expected, &**inner) {
                 // `demand::subtype` would be good enough, but using
                 // `eqtype` turns out to be equally general. See (*)
                 // below for details.
-                demand::eqtype(fcx, pat.span, expected, rptr_ty);
+
+                // Take region, inner-type from expected type if we
+                // can, to avoid creating needless variables.  This
+                // also helps with the bad interactions of the given
+                // hack detailed in (*) below.
+                let (rptr_ty, inner_ty) = match expected.sty {
+                    ty::TyRef(_, mt) if mt.mutbl == mutbl => {
+                        (expected, mt.ty)
+                    }
+                    _ => {
+                        let inner_ty = fcx.infcx().next_ty_var();
+                        let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
+                        let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
+                        let rptr_ty = tcx.mk_ref(tcx.mk_region(region), mt);
+                        demand::eqtype(fcx, pat.span, expected, rptr_ty);
+                        (rptr_ty, inner_ty)
+                    }
+                };
+
                 fcx.write_ty(pat.id, rptr_ty);
                 check_pat(pcx, &**inner, inner_ty);
             } else {
@@ -530,7 +544,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx hir::Pat,
     let tcx = pcx.fcx.ccx.tcx;
 
     let def = tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
-    let variant = match fcx.def_struct_variant(def) {
+    let variant = match fcx.def_struct_variant(def, path.span) {
         Some((_, variant)) => variant,
         None => {
             let name = pprust::path_to_string(path);
@@ -706,25 +720,25 @@ pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
 
     // Typecheck each field.
     for &Spanned { node: ref field, span } in fields {
-        let field_ty = match used_fields.entry(field.ident.name) {
+        let field_ty = match used_fields.entry(field.name) {
             Occupied(occupied) => {
                 span_err!(tcx.sess, span, E0025,
                     "field `{}` bound multiple times in the pattern",
-                    field.ident);
+                    field.name);
                 span_note!(tcx.sess, *occupied.get(),
                     "field `{}` previously bound here",
-                    field.ident);
+                    field.name);
                 tcx.types.err
             }
             Vacant(vacant) => {
                 vacant.insert(span);
-                field_map.get(&field.ident.name)
+                field_map.get(&field.name)
                     .map(|f| pcx.fcx.field_ty(span, f, substs))
                     .unwrap_or_else(|| {
                         span_err!(tcx.sess, span, E0026,
                             "struct `{}` does not have a field named `{}`",
                             tcx.item_path_str(variant.did),
-                            field.ident);
+                            field.name);
                         tcx.types.err
                     })
             }
index 948b7dd15619236b890da48ed984e5d23faf7e77..dcecec7007d52c2254608eaa8fe694f42d1f9c11 100644 (file)
@@ -25,7 +25,8 @@ use super::UnresolvedTypeAction;
 use super::write_call;
 
 use CrateCtxt;
-use middle::def_id::{DefId, LOCAL_CRATE};
+use metadata::cstore::LOCAL_CRATE;
+use middle::def_id::DefId;
 use middle::infer;
 use middle::ty::{self, LvaluePreference, Ty};
 use syntax::codemap::Span;
index 98c8c0a319946ce04ded756353d81b43f05ded8b..13e5e46ed27002fe4109908a6976a6a5a7af164d 100644 (file)
@@ -49,7 +49,8 @@ use middle::ty::{self, Ty, HasTypeFlags};
 use middle::ty::cast::{CastKind, CastTy};
 use syntax::codemap::Span;
 use rustc_front::hir;
-use rustc_front::hir::UintTy::TyU8;
+use syntax::ast;
+use syntax::ast::UintTy::TyU8;
 
 
 /// Reifies a cast check to be checked once we have full type information for
@@ -245,7 +246,7 @@ impl<'tcx> CastCheck<'tcx> {
             (_, Int(Bool)) => Err(CastError::CastToBool),
 
             // * -> Char
-            (Int(U(hir::TyU8)), Int(Char)) => Ok(CastKind::U8CharCast), // u8-char-cast
+            (Int(U(ast::TyU8)), Int(Char)) => Ok(CastKind::U8CharCast), // u8-char-cast
             (_, Int(Char)) => Err(CastError::CastToChar),
 
             // prim -> float,ptr
index 82c898214c5b69f23fcac152225c3587d8c7fea0..4f7a6395395461f4d444916b0934d5e5d3f4a42f 100644 (file)
@@ -13,7 +13,6 @@
 use super::{check_fn, Expectation, FnCtxt};
 
 use astconv;
-use middle::def_id::DefId;
 use middle::subst;
 use middle::ty::{self, ToPolyTraitRef, Ty};
 use std::cmp;
@@ -46,7 +45,7 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                           decl: &'tcx hir::FnDecl,
                           body: &'tcx hir::Block,
                           expected_sig: Option<ty::FnSig<'tcx>>) {
-    let expr_def_id = DefId::local(expr.id);
+    let expr_def_id = fcx.tcx().map.local_def_id(expr.id);
 
     debug!("check_closure opt_kind={:?} expected_sig={:?}",
            opt_kind,
index 6d8b757d167206dcac3f80027155211ee22cffa9..c46f386af277a7a2886b92d8dddca7338ac8aabb 100644 (file)
@@ -169,8 +169,8 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
 
     // Create a parameter environment that represents the implementation's
     // method.
-    let impl_param_env =
-        ty::ParameterEnvironment::for_item(tcx, impl_m.def_id.node);
+    let impl_m_node_id = tcx.map.as_local_node_id(impl_m.def_id).unwrap();
+    let impl_param_env = ty::ParameterEnvironment::for_item(tcx, impl_m_node_id);
 
     // Create mapping from impl to skolemized.
     let impl_to_skol_substs = &impl_param_env.free_substs;
@@ -428,8 +428,8 @@ pub fn compare_const_impl<'tcx>(tcx: &ty::ctxt<'tcx>,
 
     // Create a parameter environment that represents the implementation's
     // method.
-    let impl_param_env =
-        ty::ParameterEnvironment::for_item(tcx, impl_c.def_id.node);
+    let impl_c_node_id = tcx.map.as_local_node_id(impl_c.def_id).unwrap();
+    let impl_param_env = ty::ParameterEnvironment::for_item(tcx, impl_c_node_id);
 
     // Create mapping from impl to skolemized.
     let impl_to_skol_substs = &impl_param_env.free_substs;
index a8c77f863b7008175a9df4d2a601aebf1f55d5ed..d68959b99be0fee092346608b85510357499050e 100644 (file)
@@ -10,7 +10,7 @@
 
 use check::regionck::{self, Rcx};
 
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::DefId;
 use middle::free_region::FreeRegionMap;
 use middle::infer;
 use middle::region;
@@ -77,11 +77,12 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
     drop_impl_ty: &ty::Ty<'tcx>,
     self_type_did: DefId) -> Result<(), ()>
 {
-    assert!(drop_impl_did.is_local() && self_type_did.is_local());
+    let drop_impl_node_id = tcx.map.as_local_node_id(drop_impl_did).unwrap();
+    let self_type_node_id = tcx.map.as_local_node_id(self_type_did).unwrap();
 
     // check that the impl type can be made to match the trait type.
 
-    let impl_param_env = ty::ParameterEnvironment::for_item(tcx, self_type_did.node);
+    let impl_param_env = ty::ParameterEnvironment::for_item(tcx, self_type_node_id);
     let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(impl_param_env), true);
 
     let named_type = tcx.lookup_item_type(self_type_did).ty;
@@ -96,7 +97,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
                                    named_type, fresh_impl_self_ty) {
         span_err!(tcx.sess, drop_impl_span, E0366,
                   "Implementations of Drop cannot be specialized");
-        let item_span = tcx.map.span(self_type_did.node);
+        let item_span = tcx.map.span(self_type_node_id);
         tcx.sess.span_note(item_span,
                            "Use same sequence of generic type and region \
                             parameters that is on the struct/enum definition");
@@ -110,7 +111,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
     }
 
     let free_regions = FreeRegionMap::new();
-    infcx.resolve_regions_and_report_errors(&free_regions, drop_impl_did.node);
+    infcx.resolve_regions_and_report_errors(&free_regions, drop_impl_node_id);
     Ok(())
 }
 
@@ -158,7 +159,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
     // absent. So we report an error that the Drop impl injected a
     // predicate that is not present on the struct definition.
 
-    assert_eq!(self_type_did.krate, LOCAL_CRATE);
+    let self_type_node_id = tcx.map.as_local_node_id(self_type_did).unwrap();
 
     let drop_impl_span = tcx.map.def_id_span(drop_impl_did, codemap::DUMMY_SP);
 
@@ -184,7 +185,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
     for predicate in predicates {
         // (We do not need to worry about deep analysis of type
         // expressions etc because the Drop impls are already forced
-        // to take on a structure that is roughly a alpha-renaming of
+        // to take on a structure that is roughly an alpha-renaming of
         // the generic parameters of the item definition.)
 
         // This path now just checks *all* predicates via the direct
@@ -195,7 +196,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
         // repeated `contains` calls.
 
         if !assumptions_in_impl_context.contains(&predicate) {
-            let item_span = tcx.map.span(self_type_did.node);
+            let item_span = tcx.map.span(self_type_node_id);
             span_err!(tcx.sess, drop_impl_span, E0367,
                       "The requirement `{}` is added only by the Drop impl.", predicate);
             tcx.sess.span_note(item_span,
@@ -216,19 +217,16 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
 ///
 /// ----
 ///
-/// The Drop Check Rule is the following:
+/// The simplified (*) Drop Check Rule is the following:
 ///
 /// Let `v` be some value (either temporary or named) and 'a be some
 /// lifetime (scope). If the type of `v` owns data of type `D`, where
 ///
-/// * (1.) `D` has a lifetime- or type-parametric Drop implementation, and
-/// * (2.) the structure of `D` can reach a reference of type `&'a _`, and
-/// * (3.) either:
-///   * (A.) the Drop impl for `D` instantiates `D` at 'a directly,
-///          i.e. `D<'a>`, or,
-///   * (B.) the Drop impl for `D` has some type parameter with a
-///          trait bound `T` where `T` is a trait that has at least
-///          one method,
+/// * (1.) `D` has a lifetime- or type-parametric Drop implementation,
+///        (where that `Drop` implementation does not opt-out of
+///         this check via the `unsafe_destructor_blind_to_params`
+///         attribute), and
+/// * (2.) the structure of `D` can reach a reference of type `&'a _`,
 ///
 /// then 'a must strictly outlive the scope of v.
 ///
@@ -236,6 +234,35 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
 ///
 /// This function is meant to by applied to the type for every
 /// expression in the program.
+///
+/// ----
+///
+/// (*) The qualifier "simplified" is attached to the above
+/// definition of the Drop Check Rule, because it is a simplification
+/// of the original Drop Check rule, which attempted to prove that
+/// some `Drop` implementations could not possibly access data even if
+/// it was technically reachable, due to parametricity.
+///
+/// However, (1.) parametricity on its own turned out to be a
+/// necessary but insufficient condition, and (2.)  future changes to
+/// the language are expected to make it impossible to ensure that a
+/// `Drop` implementation is actually parametric with respect to any
+/// particular type parameter. (In particular, impl specialization is
+/// expected to break the needed parametricity property beyond
+/// repair.)
+///
+/// Therefore we have scaled back Drop-Check to a more conservative
+/// rule that does not attempt to deduce whether a `Drop`
+/// implementation could not possible access data of a given lifetime;
+/// instead Drop-Check now simply assumes that if a destructor has
+/// access (direct or indirect) to a lifetime parameter, then that
+/// lifetime must be forced to outlive that destructor's dynamic
+/// extent. We then provide the `unsafe_destructor_blind_to_params`
+/// attribute as a way for destructor implementations to opt-out of
+/// this conservative assumption (and thus assume the obligation of
+/// ensuring that they do not access data nor invoke methods of
+/// values that have been previously dropped).
+///
 pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
                                                          typ: ty::Ty<'tcx>,
                                                          span: Span,
@@ -355,13 +382,18 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>(
     // borrowed data reachable via `typ` must outlive the parent
     // of `scope`. This is handled below.
     //
-    // However, there is an important special case: by
-    // parametricity, any generic type parameters have *no* trait
-    // bounds in the Drop impl can not be used in any way (apart
-    // from being dropped), and thus we can treat data borrowed
-    // via such type parameters remains unreachable.
+    // However, there is an important special case: for any Drop
+    // impl that is tagged as "blind" to their parameters,
+    // we assume that data borrowed via such type parameters
+    // remains unreachable via that Drop impl.
+    //
+    // For example, consider:
+    //
+    // ```rust
+    // #[unsafe_destructor_blind_to_params]
+    // impl<T> Drop for Vec<T> { ... }
+    // ```
     //
-    // For example, consider `impl<T> Drop for Vec<T> { ... }`,
     // which does have to be able to drop instances of `T`, but
     // otherwise cannot read data from `T`.
     //
@@ -369,16 +401,6 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>(
     // unbounded type parameter `T`, we must resume the recursive
     // analysis on `T` (since it would be ignored by
     // type_must_outlive).
-    //
-    // FIXME (pnkfelix): Long term, we could be smart and actually
-    // feed which generic parameters can be ignored *into* `fn
-    // type_must_outlive` (or some generalization thereof). But
-    // for the short term, it probably covers most cases of
-    // interest to just special case Drop impls where: (1.) there
-    // are no generic lifetime parameters and (2.)  *all* generic
-    // type parameters are unbounded.  If both conditions hold, we
-    // simply skip the `type_must_outlive` call entirely (but
-    // resume the recursive checking of the type-substructure).
     if has_dtor_of_interest(tcx, ty) {
         debug!("iterate_over_potentially_unsafe_regions_in_type \
                 {}ty: {} - is a dtorck type!",
index e7c7b5831d0fc97c20bf9c1fd3f681c7d25e80eb..4afc610f63ea553e4dc803006467815e7f740e4d 100644 (file)
@@ -13,7 +13,6 @@
 
 use astconv::AstConv;
 use intrinsics;
-use middle::def_id::DefId;
 use middle::subst;
 use middle::ty::FnSig;
 use middle::ty::{self, Ty};
@@ -22,6 +21,7 @@ use {CrateCtxt, require_same_types};
 
 use std::collections::{HashMap};
 use syntax::abi;
+use syntax::ast;
 use syntax::attr::AttrMetaMethods;
 use syntax::codemap::Span;
 use syntax::parse::token;
@@ -42,7 +42,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: &ty::ctxt<'tcx>, it: &hir::ForeignItem,
             variadic: false,
         }),
     }));
-    let i_ty = tcx.lookup_item_type(DefId::local(it.id));
+    let i_ty = tcx.lookup_item_type(tcx.map.local_def_id(it.id));
     let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
     if i_n_tps != n_tps {
         span_err!(tcx.sess, it.span, E0094,
@@ -72,7 +72,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
     }
 
     let tcx = ccx.tcx;
-    let name = it.ident.name.as_str();
+    let name = it.name.as_str();
     let (n_tps, inputs, output) = if name.starts_with("atomic_") {
         let split : Vec<&str> = name.split('_').collect();
         assert!(split.len() >= 2, "Atomic intrinsic not correct format");
@@ -364,9 +364,9 @@ pub fn check_platform_intrinsic_type(ccx: &CrateCtxt,
     };
 
     let tcx = ccx.tcx;
-    let i_ty = tcx.lookup_item_type(DefId::local(it.id));
+    let i_ty = tcx.lookup_item_type(tcx.map.local_def_id(it.id));
     let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
-    let name = it.ident.name.as_str();
+    let name = it.name.as_str();
 
     let (n_tps, inputs, output) = match &*name {
         "simd_eq" | "simd_ne" | "simd_lt" | "simd_le" | "simd_gt" | "simd_ge" => {
@@ -470,22 +470,22 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
         },
         // (The width we pass to LLVM doesn't concern the type checker.)
         Integer(signed, bits, _llvm_width) => match (signed, bits, &t.sty) {
-            (true,  8,  &ty::TyInt(hir::IntTy::TyI8)) |
-            (false, 8,  &ty::TyUint(hir::UintTy::TyU8)) |
-            (true,  16, &ty::TyInt(hir::IntTy::TyI16)) |
-            (false, 16, &ty::TyUint(hir::UintTy::TyU16)) |
-            (true,  32, &ty::TyInt(hir::IntTy::TyI32)) |
-            (false, 32, &ty::TyUint(hir::UintTy::TyU32)) |
-            (true,  64, &ty::TyInt(hir::IntTy::TyI64)) |
-            (false, 64, &ty::TyUint(hir::UintTy::TyU64)) => {},
+            (true,  8,  &ty::TyInt(ast::IntTy::TyI8)) |
+            (false, 8,  &ty::TyUint(ast::UintTy::TyU8)) |
+            (true,  16, &ty::TyInt(ast::IntTy::TyI16)) |
+            (false, 16, &ty::TyUint(ast::UintTy::TyU16)) |
+            (true,  32, &ty::TyInt(ast::IntTy::TyI32)) |
+            (false, 32, &ty::TyUint(ast::UintTy::TyU32)) |
+            (true,  64, &ty::TyInt(ast::IntTy::TyI64)) |
+            (false, 64, &ty::TyUint(ast::UintTy::TyU64)) => {},
             _ => simple_error(&format!("`{}`", t),
                               &format!("`{}{n}`",
                                        if signed {"i"} else {"u"},
                                        n = bits)),
         },
         Float(bits) => match (bits, &t.sty) {
-            (32, &ty::TyFloat(hir::FloatTy::TyF32)) |
-            (64, &ty::TyFloat(hir::FloatTy::TyF64)) => {},
+            (32, &ty::TyFloat(ast::FloatTy::TyF32)) |
+            (64, &ty::TyFloat(ast::FloatTy::TyF64)) => {},
             _ => simple_error(&format!("`{}`", t),
                               &format!("`f{n}`", n = bits)),
         },
index 454c11db263e17e924864379b5403efd189c8161..72131627aa5d4dd3303d2ba5a7b307d8de50174e 100644 (file)
@@ -103,22 +103,23 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
         // Unify the (adjusted) self type with what the method expects.
         self.unify_receivers(self_ty, method_self_ty);
 
-        // Add any trait/regions obligations specified on the method's type parameters.
-        self.add_obligations(&pick, &all_substs, &method_predicates);
-
-        // Create the final `MethodCallee`.
+        // Create the method type
         let method_ty = pick.item.as_opt_method().unwrap();
         let fty = self.tcx().mk_fn(None, self.tcx().mk_bare_fn(ty::BareFnTy {
             sig: ty::Binder(method_sig),
             unsafety: method_ty.fty.unsafety,
             abi: method_ty.fty.abi.clone(),
         }));
+
+        // Add any trait/regions obligations specified on the method's type parameters.
+        self.add_obligations(fty, &all_substs, &method_predicates);
+
+        // Create the final `MethodCallee`.
         let callee = ty::MethodCallee {
             def_id: pick.item.def_id(),
             ty: fty,
             substs: self.tcx().mk_substs(all_substs)
         };
-
         // If this is an `&mut self` method, bias the receiver
         // expression towards mutability (this will switch
         // e.g. `Deref` to `DerefMut` in overloaded derefs and so on).
@@ -422,11 +423,11 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
     }
 
     fn add_obligations(&mut self,
-                       pick: &probe::Pick<'tcx>,
+                       fty: Ty<'tcx>,
                        all_substs: &subst::Substs<'tcx>,
                        method_predicates: &ty::InstantiatedPredicates<'tcx>) {
-        debug!("add_obligations: pick={:?} all_substs={:?} method_predicates={:?}",
-               pick,
+        debug!("add_obligations: fty={:?} all_substs={:?} method_predicates={:?}",
+               fty,
                all_substs,
                method_predicates);
 
@@ -439,6 +440,11 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
         self.fcx.add_wf_bounds(
             all_substs,
             self.call_expr);
+
+        // the function type must also be well-formed (this is not
+        // implied by the substs being well-formed because of inherent
+        // impls and late-bound regions - see issue #28609).
+        self.fcx.register_wf_obligation(fty, self.span, traits::MiscObligation);
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -468,7 +474,6 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
         loop {
             let last = exprs[exprs.len() - 1];
             match last.node {
-                hir::ExprParen(ref expr) |
                 hir::ExprField(ref expr, _) |
                 hir::ExprTupField(ref expr, _) |
                 hir::ExprIndex(ref expr, _) |
index edf1cc9b7ef38c31a4812bae98b31b35a2c56d94..e0ad51b4ea1b54532dd56d0fe0d763d7aa5ab9ed 100644 (file)
@@ -255,6 +255,9 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         traits::ObligationCause::misc(span, fcx.body_id),
         &method_bounds);
 
+    // Also register an obligation for the method type being well-formed.
+    fcx.register_wf_obligation(fty, span, traits::MiscObligation);
+
     // FIXME(#18653) -- Try to resolve obligations, giving us more
     // typing information, which can sometimes be needed to avoid
     // pathological region inference failures.
index f65602d9aaccb0d9e9d1a348fd709cf79f9e32a3..c63b081c73c4872cb7afafb0eb0a6635f926083a 100644 (file)
@@ -319,51 +319,51 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                 let lang_def_id = self.tcx().lang_items.mut_ptr_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyInt(hir::TyI8) => {
+            ty::TyInt(ast::TyI8) => {
                 let lang_def_id = self.tcx().lang_items.i8_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyInt(hir::TyI16) => {
+            ty::TyInt(ast::TyI16) => {
                 let lang_def_id = self.tcx().lang_items.i16_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyInt(hir::TyI32) => {
+            ty::TyInt(ast::TyI32) => {
                 let lang_def_id = self.tcx().lang_items.i32_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyInt(hir::TyI64) => {
+            ty::TyInt(ast::TyI64) => {
                 let lang_def_id = self.tcx().lang_items.i64_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyInt(hir::TyIs) => {
+            ty::TyInt(ast::TyIs) => {
                 let lang_def_id = self.tcx().lang_items.isize_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyUint(hir::TyU8) => {
+            ty::TyUint(ast::TyU8) => {
                 let lang_def_id = self.tcx().lang_items.u8_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyUint(hir::TyU16) => {
+            ty::TyUint(ast::TyU16) => {
                 let lang_def_id = self.tcx().lang_items.u16_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyUint(hir::TyU32) => {
+            ty::TyUint(ast::TyU32) => {
                 let lang_def_id = self.tcx().lang_items.u32_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyUint(hir::TyU64) => {
+            ty::TyUint(ast::TyU64) => {
                 let lang_def_id = self.tcx().lang_items.u64_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyUint(hir::TyUs) => {
+            ty::TyUint(ast::TyUs) => {
                 let lang_def_id = self.tcx().lang_items.usize_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyFloat(hir::TyF32) => {
+            ty::TyFloat(ast::TyF32) => {
                 let lang_def_id = self.tcx().lang_items.f32_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
-            ty::TyFloat(hir::TyF64) => {
+            ty::TyFloat(ast::TyF64) => {
                 let lang_def_id = self.tcx().lang_items.f64_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
index 6961f3444d90875bdad2183ba6ba8d69b73e6de5..f597820639c24ea3e12d3131170596d2953078c5 100644 (file)
@@ -15,6 +15,7 @@ use CrateCtxt;
 
 use astconv::AstConv;
 use check::{self, FnCtxt};
+use front::map as hir_map;
 use middle::ty::{self, Ty, ToPolyTraitRef, ToPredicate, HasTypeFlags};
 use middle::def;
 use middle::def_id::DefId;
@@ -22,6 +23,7 @@ use middle::lang_items::FnOnceTraitLangItem;
 use middle::subst::Substs;
 use middle::traits::{Obligation, SelectionContext};
 use metadata::{csearch, cstore, decoder};
+use util::nodemap::{FnvHashSet};
 
 use syntax::ast;
 use syntax::codemap::Span;
@@ -182,7 +184,14 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 CandidateSource::ImplSource(impl_did) => {
                     // Provide the best span we can. Use the item, if local to crate, else
                     // the impl, if local to crate (item may be defaulted), else the call site.
-                    let item = impl_item(fcx.tcx(), impl_did, item_name).unwrap();
+                    let item = impl_item(fcx.tcx(), impl_did, item_name)
+                        .or_else(|| {
+                            trait_item(
+                                fcx.tcx(),
+                                fcx.tcx().impl_trait_ref(impl_did).unwrap().def_id,
+                                item_name
+                            )
+                        }).unwrap();
                     let impl_span = fcx.tcx().map.def_id_span(impl_did, span);
                     let item_span = fcx.tcx().map.def_id_span(item.def_id(), impl_span);
 
@@ -357,13 +366,11 @@ impl PartialOrd for TraitInfo {
 }
 impl Ord for TraitInfo {
     fn cmp(&self, other: &TraitInfo) -> Ordering {
-        // accessible traits are more important/relevant than
-        // inaccessible ones, local crates are more important than
-        // remote ones (local: cnum == 0), and NodeIds just for
-        // totality.
+        // local crates are more important than remote ones (local:
+        // cnum == 0), and otherwise we throw in the defid for totality
 
-        let lhs = (other.def_id.krate, other.def_id.node);
-        let rhs = (self.def_id.krate, self.def_id.node);
+        let lhs = (other.def_id.krate, other.def_id);
+        let rhs = (self.def_id.krate, self.def_id);
         lhs.cmp(&rhs)
     }
 }
@@ -378,14 +385,16 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
         // Crate-local:
         //
         // meh.
-        struct Visitor<'a> {
+        struct Visitor<'a, 'tcx:'a> {
+            map: &'a hir_map::Map<'tcx>,
             traits: &'a mut AllTraitsVec,
         }
-        impl<'v, 'a> visit::Visitor<'v> for Visitor<'a> {
+        impl<'v, 'a, 'tcx> visit::Visitor<'v> for Visitor<'a, 'tcx> {
             fn visit_item(&mut self, i: &'v hir::Item) {
                 match i.node {
                     hir::ItemTrait(..) => {
-                        self.traits.push(TraitInfo::new(DefId::local(i.id)));
+                        let def_id = self.map.local_def_id(i.id);
+                        self.traits.push(TraitInfo::new(def_id));
                     }
                     _ => {}
                 }
@@ -393,11 +402,14 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
             }
         }
         visit::walk_crate(&mut Visitor {
+            map: &ccx.tcx.map,
             traits: &mut traits
         }, ccx.tcx.map.krate());
 
         // Cross-crate:
+        let mut external_mods = FnvHashSet();
         fn handle_external_def(traits: &mut AllTraitsVec,
+                               external_mods: &mut FnvHashSet<DefId>,
                                ccx: &CrateCtxt,
                                cstore: &cstore::CStore,
                                dl: decoder::DefLike) {
@@ -406,8 +418,12 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
                     traits.push(TraitInfo::new(did));
                 }
                 decoder::DlDef(def::DefMod(did)) => {
+                    if !external_mods.insert(did) {
+                        return;
+                    }
                     csearch::each_child_of_item(cstore, did, |dl, _, _| {
-                        handle_external_def(traits, ccx, cstore, dl)
+                        handle_external_def(traits, external_mods,
+                                            ccx, cstore, dl)
                     })
                 }
                 _ => {}
@@ -416,7 +432,9 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
         let cstore = &ccx.tcx.sess.cstore;
         cstore.iter_crate_data(|cnum, _| {
             csearch::each_top_level_item_of_crate(cstore, cnum, |dl, _, _| {
-                handle_external_def(&mut traits, ccx, cstore, dl)
+                handle_external_def(&mut traits,
+                                    &mut external_mods,
+                                    ccx, cstore, dl)
             })
         });
 
index b07168966c191417d3d9bc8d835e1f85175228bf..f085ce23e3f0c0d46e9cd527c945f03d7b6af4ed 100644 (file)
@@ -83,9 +83,10 @@ use self::TupleArgumentsFlag::*;
 use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
 use check::_match::pat_ctxt;
 use fmt_macros::{Parser, Piece, Position};
+use metadata::cstore::LOCAL_CRATE;
 use middle::astconv_util::prohibit_type_params;
 use middle::def;
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::DefId;
 use middle::infer;
 use middle::infer::type_variable;
 use middle::pat_util::{self, pat_id_map};
@@ -114,10 +115,11 @@ use util::lev_distance::lev_distance;
 use std::cell::{Cell, Ref, RefCell};
 use std::collections::{HashSet};
 use std::mem::replace;
-use std::slice;
 use syntax::abi;
 use syntax::ast;
-use syntax::codemap::{self, Span};
+use syntax::attr;
+use syntax::attr::AttrMetaMethods;
+use syntax::codemap::{self, Span, Spanned};
 use syntax::owned_slice::OwnedSlice;
 use syntax::parse::token::{self, InternedString};
 use syntax::ptr::P;
@@ -125,10 +127,9 @@ use syntax::ptr::P;
 use rustc_front::visit::{self, Visitor};
 use rustc_front::hir;
 use rustc_front::hir::Visibility;
-use rustc_front::attr;
-use rustc_front::attr::AttrMetaMethods;
 use rustc_front::hir::{Item, ItemImpl};
 use rustc_front::print::pprust;
+use rustc_back::slice;
 
 mod assoc;
 pub mod dropck;
@@ -268,7 +269,7 @@ impl UnsafetyState {
                         (unsafety, blk.id, self.unsafe_push_count.checked_sub(1).unwrap()),
                     hir::UnsafeBlock(..) =>
                         (hir::Unsafety::Unsafe, blk.id, self.unsafe_push_count),
-                    hir::DefaultBlock =>
+                    hir::DefaultBlock | hir::PushUnstableBlock | hir:: PopUnstableBlock =>
                         (unsafety, self.def, self.unsafe_push_count),
                 };
                 UnsafetyState{ def: def,
@@ -376,6 +377,11 @@ impl<'a, 'tcx> Visitor<'tcx> for CheckItemTypesVisitor<'a, 'tcx> {
             hir::TyFixedLengthVec(_, ref expr) => {
                 check_const_in_type(self.ccx, &**expr, self.ccx.tcx.types.usize);
             }
+            hir::TyBareFn(ref function_declaration) => {
+                visit::walk_fn_decl_nopat(self, &function_declaration.decl);
+                walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes);
+                return
+            }
             _ => {}
         }
 
@@ -560,6 +566,10 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
                 self.visit_ty(&**ty);
                 check_expr_with_hint(self.fcx, &**count_expr, self.fcx.tcx().types.usize);
             }
+            hir::TyBareFn(ref function_declaration) => {
+                visit::walk_fn_decl_nopat(self, &function_declaration.decl);
+                walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes);
+            }
             _ => visit::walk_ty(self, t)
         }
     }
@@ -678,15 +688,15 @@ pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
 
     check_representable(tcx, span, id, "struct");
 
-    if tcx.lookup_simd(DefId::local(id)) {
+    if tcx.lookup_simd(ccx.tcx.map.local_def_id(id)) {
         check_simd(tcx, span, id);
     }
 }
 
 pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
-    debug!("check_item_type(it.id={}, it.ident={})",
+    debug!("check_item_type(it.id={}, it.name={})",
            it.id,
-           ccx.tcx.item_path_str(DefId::local(it.id)));
+           ccx.tcx.item_path_str(ccx.tcx.map.local_def_id(it.id)));
     let _indenter = indenter();
     match it.node {
       // Consts can play a role in type-checking, so they are included here.
@@ -700,8 +710,8 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
       }
       hir::ItemFn(..) => {} // entirely within check_item_body
       hir::ItemImpl(_, _, _, _, _, ref impl_items) => {
-          debug!("ItemImpl {} with id {}", it.ident, it.id);
-          match ccx.tcx.impl_trait_ref(DefId::local(it.id)) {
+          debug!("ItemImpl {} with id {}", it.name, it.id);
+          match ccx.tcx.impl_trait_ref(ccx.tcx.map.local_def_id(it.id)) {
               Some(impl_trait_ref) => {
                 check_impl_items_against_trait(ccx,
                                                it.span,
@@ -732,7 +742,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
             }
         } else {
             for item in &m.items {
-                let pty = ccx.tcx.lookup_item_type(DefId::local(item.id));
+                let pty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(item.id));
                 if !pty.generics.types.is_empty() {
                     span_err!(ccx.tcx.sess, item.span, E0044,
                         "foreign items may not have type parameters");
@@ -752,20 +762,20 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
 }
 
 pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
-    debug!("check_item_body(it.id={}, it.ident={})",
+    debug!("check_item_body(it.id={}, it.name={})",
            it.id,
-           ccx.tcx.item_path_str(DefId::local(it.id)));
+           ccx.tcx.item_path_str(ccx.tcx.map.local_def_id(it.id)));
     let _indenter = indenter();
     match it.node {
       hir::ItemFn(ref decl, _, _, _, _, ref body) => {
-        let fn_pty = ccx.tcx.lookup_item_type(DefId::local(it.id));
+        let fn_pty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(it.id));
         let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
         check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env);
       }
       hir::ItemImpl(_, _, _, _, _, ref impl_items) => {
-        debug!("ItemImpl {} with id {}", it.ident, it.id);
+        debug!("ItemImpl {} with id {}", it.name, it.id);
 
-        let impl_pty = ccx.tcx.lookup_item_type(DefId::local(it.id));
+        let impl_pty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(it.id));
 
         for impl_item in impl_items {
             match impl_item.node {
@@ -783,7 +793,7 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
         }
       }
       hir::ItemTrait(_, _, _, ref trait_items) => {
-        let trait_def = ccx.tcx.lookup_trait_def(DefId::local(it.id));
+        let trait_def = ccx.tcx.lookup_trait_def(ccx.tcx.map.local_def_id(it.id));
         for trait_item in trait_items {
             match trait_item.node {
                 hir::ConstTraitItem(_, Some(ref expr)) => {
@@ -840,14 +850,14 @@ fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                         Position::ArgumentNamed(s) if s == "Self" => (),
                         // So is `{A}` if A is a type parameter
                         Position::ArgumentNamed(s) => match types.iter().find(|t| {
-                            t.ident.name == s
+                            t.name.as_str() == s
                         }) {
                             Some(_) => (),
                             None => {
                                 span_err!(ccx.tcx.sess, attr.span, E0230,
                                                  "there is no type parameter \
                                                           {} on trait {}",
-                                                           s, item.ident);
+                                                           s, item.name);
                             }
                         },
                         // `{:1}` and `{}` are not to be used
@@ -902,7 +912,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     // Check existing impl methods to see if they are both present in trait
     // and compatible with trait signature
     for impl_item in impl_items {
-        let ty_impl_item = ccx.tcx.impl_or_trait_item(DefId::local(impl_item.id));
+        let ty_impl_item = ccx.tcx.impl_or_trait_item(ccx.tcx.map.local_def_id(impl_item.id));
         let ty_trait_item = trait_items.iter()
             .find(|ac| ac.name() == ty_impl_item.name())
             .unwrap_or_else(|| {
@@ -980,7 +990,6 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     // Check for missing items from trait
     let provided_methods = tcx.provided_trait_methods(impl_trait_ref.def_id);
-    let associated_consts = tcx.associated_consts(impl_trait_ref.def_id);
     let mut missing_items = Vec::new();
     let mut invalidated_items = Vec::new();
     let associated_type_overridden = overridden_associated_type.is_some();
@@ -990,14 +999,13 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 let is_implemented = impl_items.iter().any(|ii| {
                     match ii.node {
                         hir::ConstImplItem(..) => {
-                            ii.ident.name == associated_const.name
+                            ii.name == associated_const.name
                         }
                         _ => false,
                     }
                 });
-                let is_provided =
-                    associated_consts.iter().any(|ac| ac.default.is_some() &&
-                                                 ac.name == associated_const.name);
+                let is_provided = associated_const.has_value;
+
                 if !is_implemented {
                     if !is_provided {
                         missing_items.push(associated_const.name);
@@ -1011,7 +1019,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                     impl_items.iter().any(|ii| {
                         match ii.node {
                             hir::MethodImplItem(..) => {
-                                ii.ident.name == trait_method.name
+                                ii.name == trait_method.name
                             }
                             _ => false,
                         }
@@ -1030,7 +1038,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 let is_implemented = impl_items.iter().any(|ii| {
                     match ii.node {
                         hir::TypeImplItem(_) => {
-                            ii.ident.name == associated_type.name
+                            ii.name == associated_type.name
                         }
                         _ => false,
                     }
@@ -1060,7 +1068,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         span_err!(tcx.sess, invalidator.span, E0399,
                   "the following trait items need to be reimplemented \
                    as `{}` was overridden: `{}`",
-                  invalidator.ident,
+                  invalidator.name,
                   invalidated_items.iter()
                                    .map(|name| name.to_string())
                                    .collect::<Vec<_>>().join("`, `"))
@@ -1310,9 +1318,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         match self.inh.locals.borrow().get(&nid) {
             Some(&t) => t,
             None => {
-                self.tcx().sess.span_err(
-                    span,
-                    &format!("no type for local variable {}", nid));
+                span_err!(self.tcx().sess, span, E0513,
+                          "no type for local variable {}",
+                          nid);
                 self.tcx().types.err
             }
         }
@@ -1456,7 +1464,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     /// Return the dict-like variant corresponding to a given `Def`.
     pub fn def_struct_variant(&self,
-                              def: def::Def)
+                              def: def::Def,
+                              span: Span)
                               -> Option<(ty::AdtDef<'tcx>, ty::VariantDef<'tcx>)>
     {
         let (adt, variant) = match def {
@@ -1475,13 +1484,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             _ => return None
         };
 
-        if let ty::VariantKind::Dict = variant.kind() {
+        let var_kind = variant.kind();
+        if var_kind == ty::VariantKind::Struct {
             Some((adt, variant))
-        } else {
-            None
-        }
-    }
+        } else if var_kind == ty::VariantKind::Unit {
+            if !self.tcx().sess.features.borrow().braced_empty_structs {
+                self.tcx().sess.span_err(span, "empty structs and enum variants \
+                                                with braces are unstable");
+                fileline_help!(self.tcx().sess, span, "add #![feature(braced_empty_structs)] to \
+                                                       the crate features to enable");
+            }
 
+             Some((adt, variant))
+         } else {
+             None
+         }
+    }
 
     pub fn write_nil(&self, node_id: ast::NodeId) {
         self.write_ty(node_id, self.tcx().mk_nil());
@@ -1549,21 +1567,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     pub fn to_ty(&self, ast_t: &hir::Ty) -> Ty<'tcx> {
         let t = ast_ty_to_ty(self, self, ast_t);
-
-        // Generally speaking, we must check that types entered by the
-        // user are well-formed. This is not true for `_`, since those
-        // types are generated by inference. Now, you might think that
-        // we could as well generate a WF obligation -- but
-        // unfortunately that breaks code like `foo as *const _`,
-        // because those type variables wind up being unconstrained
-        // until very late. Nasty. Probably it'd be best to refactor
-        // that code path, but that's tricky because of
-        // defaults. Argh!
-        match ast_t.node {
-            hir::TyInfer => { }
-            _ => { self.register_wf_obligation(t, ast_t.span, traits::MiscObligation); }
-        }
-
+        self.register_wf_obligation(t, ast_t.span, traits::MiscObligation);
         t
     }
 
@@ -1816,7 +1820,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // There is a possibility that this algorithm will have to run an arbitrary number of times
         // to terminate so we bound it by the compiler's recursion limit.
-        for _ in (0..self.tcx().sess.recursion_limit.get()) {
+        for _ in 0..self.tcx().sess.recursion_limit.get() {
             // First we try to solve all obligations, it is possible that the last iteration
             // has made it possible to make more progress.
             self.select_obligations_where_possible();
@@ -1884,7 +1888,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
 
             // If there are no more fallbacks to apply at this point we have applied all possible
-            // defaults and type inference will procede as normal.
+            // defaults and type inference will proceed as normal.
             if unbound_tyvars.is_empty() {
                 break;
             }
@@ -1946,7 +1950,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             .unwrap_or(type_variable::Default {
                                 ty: self.infcx().next_ty_var(),
                                 origin_span: codemap::DUMMY_SP,
-                                def_id: DefId::local(0) // what do I put here?
+                                def_id: self.tcx().map.local_def_id(0) // what do I put here?
                             });
 
                     // This is to ensure that we elimnate any non-determinism from the error
@@ -2228,7 +2232,7 @@ fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 {
     match method {
         Some(method) => {
-            // extract method method return type, which will be &T;
+            // extract method return type, which will be &T;
             // all LB regions should have been instantiated during method lookup
             let ret_ty = method.ty.fn_ret();
             let ret_ty = fcx.tcx().no_late_bound_regions(&ret_ty).unwrap().unwrap();
@@ -2311,7 +2315,7 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
     // First, try built-in indexing.
     match (adjusted_ty.builtin_index(), &index_ty.sty) {
-        (Some(ty), &ty::TyUint(hir::TyUs)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
+        (Some(ty), &ty::TyUint(ast::TyUs)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
             debug!("try_index_step: success, using built-in indexing");
             // If we had `[T; N]`, we should've caught it before unsizing to `[T]`.
             assert!(!unsize);
@@ -2575,21 +2579,21 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             let arg_ty = structurally_resolved_type(fcx, arg.span,
                                                     fcx.expr_ty(&**arg));
             match arg_ty.sty {
-                ty::TyFloat(hir::TyF32) => {
+                ty::TyFloat(ast::TyF32) => {
                     fcx.type_error_message(arg.span,
                                            |t| {
                         format!("can't pass an {} to variadic \
                                  function, cast to c_double", t)
                     }, arg_ty, None);
                 }
-                ty::TyInt(hir::TyI8) | ty::TyInt(hir::TyI16) | ty::TyBool => {
+                ty::TyInt(ast::TyI8) | ty::TyInt(ast::TyI16) | ty::TyBool => {
                     fcx.type_error_message(arg.span, |t| {
                         format!("can't pass {} to variadic \
                                  function, cast to c_int",
                                        t)
                     }, arg_ty, None);
                 }
-                ty::TyUint(hir::TyU8) | ty::TyUint(hir::TyU16) => {
+                ty::TyUint(ast::TyU8) | ty::TyUint(ast::TyU16) => {
                     fcx.type_error_message(arg.span, |t| {
                         format!("can't pass {} to variadic \
                                  function, cast to c_uint",
@@ -2618,23 +2622,23 @@ fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
 // AST fragment checking
 fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                       lit: &hir::Lit,
+                       lit: &ast::Lit,
                        expected: Expectation<'tcx>)
                        -> Ty<'tcx>
 {
     let tcx = fcx.ccx.tcx;
 
     match lit.node {
-        hir::LitStr(..) => tcx.mk_static_str(),
-        hir::LitByteStr(ref v) => {
+        ast::LitStr(..) => tcx.mk_static_str(),
+        ast::LitByteStr(ref v) => {
             tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic),
                             tcx.mk_array(tcx.types.u8, v.len()))
         }
-        hir::LitByte(_) => tcx.types.u8,
-        hir::LitChar(_) => tcx.types.char,
-        hir::LitInt(_, hir::SignedIntLit(t, _)) => tcx.mk_mach_int(t),
-        hir::LitInt(_, hir::UnsignedIntLit(t)) => tcx.mk_mach_uint(t),
-        hir::LitInt(_, hir::UnsuffixedIntLit(_)) => {
+        ast::LitByte(_) => tcx.types.u8,
+        ast::LitChar(_) => tcx.types.char,
+        ast::LitInt(_, ast::SignedIntLit(t, _)) => tcx.mk_mach_int(t),
+        ast::LitInt(_, ast::UnsignedIntLit(t)) => tcx.mk_mach_uint(t),
+        ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
             let opt_ty = expected.to_option(fcx).and_then(|ty| {
                 match ty.sty {
                     ty::TyInt(_) | ty::TyUint(_) => Some(ty),
@@ -2647,8 +2651,8 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             opt_ty.unwrap_or_else(
                 || tcx.mk_int_var(fcx.infcx().next_int_var_id()))
         }
-        hir::LitFloat(_, t) => tcx.mk_mach_float(t),
-        hir::LitFloatUnsuffixed(_) => {
+        ast::LitFloat(_, t) => tcx.mk_mach_float(t),
+        ast::LitFloatUnsuffixed(_) => {
             let opt_ty = expected.to_option(fcx).and_then(|ty| {
                 match ty.sty {
                     ty::TyFloat(_) => Some(ty),
@@ -2658,7 +2662,7 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             opt_ty.unwrap_or_else(
                 || tcx.mk_float_var(fcx.infcx().next_float_var_id()))
         }
-        hir::LitBool(_) => tcx.types.bool
+        ast::LitBool(_) => tcx.types.bool
     }
 }
 
@@ -2822,7 +2826,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
     // Checks a method call.
     fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                    expr: &'tcx hir::Expr,
-                                   method_name: hir::SpannedIdent,
+                                   method_name: Spanned<ast::Name>,
                                    args: &'tcx [P<hir::Expr>],
                                    tps: &[P<hir::Ty>],
                                    expected: Expectation<'tcx>,
@@ -2838,7 +2842,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
         let fn_ty = match method::lookup(fcx,
                                          method_name.span,
-                                         method_name.node.name,
+                                         method_name.node,
                                          expr_t,
                                          tps,
                                          expr,
@@ -2851,7 +2855,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             }
             Err(error) => {
                 method::report_error(fcx, method_name.span, expr_t,
-                                     method_name.node.name, Some(rcvr), error);
+                                     method_name.node, Some(rcvr), error);
                 fcx.write_error(expr.id);
                 fcx.tcx().types.err
             }
@@ -2918,7 +2922,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                             expr: &'tcx hir::Expr,
                             lvalue_pref: LvaluePreference,
                             base: &'tcx hir::Expr,
-                            field: &hir::SpannedIdent) {
+                            field: &Spanned<ast::Name>) {
         let tcx = fcx.ccx.tcx;
         check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
         let expr_t = structurally_resolved_type(fcx, expr.span,
@@ -2935,7 +2939,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                     ty::TyStruct(base_def, substs) => {
                         debug!("struct named {:?}",  base_t);
                         base_def.struct_variant()
-                                .find_field_named(field.node.name)
+                                .find_field_named(field.node)
                                 .map(|f| fcx.field_ty(expr.span, f, substs))
                     }
                     _ => None
@@ -2950,7 +2954,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             None => {}
         }
 
-        if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
+        if method::exists(fcx, field.span, field.node, expr_t, expr.id) {
             fcx.type_error_message(
                 field.span,
                 |actual| {
@@ -2983,10 +2987,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
     // displays hints about the closest matches in field names
     fn suggest_field_names<'tcx>(variant: ty::VariantDef<'tcx>,
-                                 field: &hir::SpannedIdent,
+                                 field: &Spanned<ast::Name>,
                                  tcx: &ty::ctxt<'tcx>,
                                  skip : Vec<InternedString>) {
-        let name = field.node.name.as_str();
+        let name = field.node.as_str();
         // only find fits with at least one matching letter
         let mut best_dist = name.len();
         let mut best = None;
@@ -3084,22 +3088,21 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                       field: &hir::Field,
                                       skip_fields: &[hir::Field]) {
         fcx.type_error_message(
-            field.ident.span,
+            field.name.span,
             |actual| if let ty::TyEnum(..) = ty.sty {
                 format!("struct variant `{}::{}` has no field named `{}`",
-                        actual, variant.name.as_str(), field.ident.node)
+                        actual, variant.name.as_str(), field.name.node)
             } else {
                 format!("structure `{}` has no field named `{}`",
-                        actual, field.ident.node)
+                        actual, field.name.node)
             },
             ty,
             None);
         // prevent all specified fields from being suggested
-        let skip_fields = skip_fields.iter().map(|ref x| x.ident.node.name.as_str());
-        suggest_field_names(variant, &field.ident, fcx.tcx(), skip_fields.collect());
+        let skip_fields = skip_fields.iter().map(|ref x| x.name.node.as_str());
+        suggest_field_names(variant, &field.name, fcx.tcx(), skip_fields.collect());
     }
 
-
     fn check_expr_struct_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                           adt_ty: Ty<'tcx>,
                                           span: Span,
@@ -3123,15 +3126,15 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         for field in ast_fields {
             let expected_field_type;
 
-            if let Some(v_field) = remaining_fields.remove(&field.ident.node.name) {
+            if let Some(v_field) = remaining_fields.remove(&field.name.node) {
                 expected_field_type = fcx.field_ty(field.span, v_field, substs);
             } else {
                 error_happened = true;
                 expected_field_type = tcx.types.err;
-                if let Some(_) = variant.find_field_named(field.ident.node.name) {
-                    span_err!(fcx.tcx().sess, field.ident.span, E0062,
+                if let Some(_) = variant.find_field_named(field.name.node) {
+                    span_err!(fcx.tcx().sess, field.name.span, E0062,
                         "field `{}` specified more than once",
-                        field.ident.node);
+                        field.name.node);
                 } else {
                     report_unknown_field(fcx, adt_ty, variant, field, ast_fields);
                 }
@@ -3184,7 +3187,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
         // Find the relevant variant
         let def = lookup_full_def(tcx, path.span, expr.id);
-        let (adt, variant) = match fcx.def_struct_variant(def) {
+        let (adt, variant) = match fcx.def_struct_variant(def, path.span) {
             Some((adt, variant)) => (adt, variant),
             None => {
                 span_err!(fcx.tcx().sess, path.span, E0071,
@@ -3215,31 +3218,16 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
     let tcx = fcx.ccx.tcx;
     let id = expr.id;
     match expr.node {
-      hir::ExprBox(ref opt_place, ref subexpr) => {
-          opt_place.as_ref().map(|place|check_expr(fcx, &**place));
-          check_expr(fcx, &**subexpr);
-
-          let mut checked = false;
-          opt_place.as_ref().map(|place| match place.node {
-              hir::ExprPath(None, ref path) => {
-                  // FIXME(pcwalton): For now we hardcode the only permissible
-                  // place: the exchange heap.
-                  let definition = lookup_full_def(tcx, path.span, place.id);
-                  let def_id = definition.def_id();
-                  let referent_ty = fcx.expr_ty(&**subexpr);
-                  if tcx.lang_items.exchange_heap() == Some(def_id) {
-                      fcx.write_ty(id, tcx.mk_box(referent_ty));
-                      checked = true
-                  }
-              }
-              _ => {}
-          });
-
-          if !checked {
-              span_err!(tcx.sess, expr.span, E0066,
-                  "only the exchange heap is currently supported");
-              fcx.write_ty(id, tcx.types.err);
-          }
+      hir::ExprBox(ref subexpr) => {
+        let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
+            match ty.sty {
+                ty::TyBox(ty) => Expectation::rvalue_hint(tcx, ty),
+                _ => NoExpectation
+            }
+        });
+        check_expr_with_expectation(fcx, subexpr, expected_inner);
+        let referent_ty = fcx.expr_ty(&**subexpr);
+        fcx.write_ty(id, tcx.mk_box(referent_ty));
       }
 
       hir::ExprLit(ref lit) => {
@@ -3253,24 +3241,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         op::check_binop_assign(fcx, expr, op, lhs, rhs);
       }
       hir::ExprUnary(unop, ref oprnd) => {
-        let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
-            match unop {
-                hir::UnUniq => match ty.sty {
-                    ty::TyBox(ty) => {
-                        Expectation::rvalue_hint(tcx, ty)
-                    }
-                    _ => {
-                        NoExpectation
-                    }
-                },
-                hir::UnNot | hir::UnNeg => {
-                    expected
-                }
-                hir::UnDeref => {
-                    NoExpectation
-                }
+        let expected_inner = match unop {
+            hir::UnNot | hir::UnNeg => {
+                expected
             }
-        });
+            hir::UnDeref => {
+                NoExpectation
+            }
+        };
         let lvalue_pref = match unop {
             hir::UnDeref => lvalue_pref,
             _ => NoPreference
@@ -3281,9 +3259,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
         if !oprnd_t.references_error() {
             match unop {
-                hir::UnUniq => {
-                    oprnd_t = tcx.mk_box(oprnd_t);
-                }
                 hir::UnDeref => {
                     oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
                     oprnd_t = match oprnd_t.builtin_deref(true, NoPreference) {
@@ -3378,7 +3353,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
           } else if let Some(hir::QSelf { position: 0, .. }) = *maybe_qself {
                 // Create some fake resolution that can't possibly be a type.
                 def::PathResolution {
-                    base_def: def::DefMod(DefId::local(ast::CRATE_NODE_ID)),
+                    base_def: def::DefMod(tcx.map.local_def_id(ast::CRATE_NODE_ID)),
                     last_private: LastMod(AllPublic),
                     depth: path.segments.len()
                 }
@@ -3446,13 +3421,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         }
         fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
       }
-      hir::ExprParen(ref a) => {
-        check_expr_with_expectation_and_lvalue_pref(fcx,
-                                                    &**a,
-                                                    expected,
-                                                    lvalue_pref);
-        fcx.write_ty(id, fcx.expr_ty(&**a));
-      }
       hir::ExprAssign(ref lhs, ref rhs) => {
         check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
 
@@ -3515,8 +3483,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
           let ret_ty = fcx.expr_ty(expr);
           fcx.register_wf_obligation(ret_ty, expr.span, traits::MiscObligation);
       }
-      hir::ExprMethodCall(ident, ref tps, ref args) => {
-          check_method_call(fcx, expr, ident, &args[..], &tps[..], expected, lvalue_pref);
+      hir::ExprMethodCall(name, ref tps, ref args) => {
+          check_method_call(fcx, expr, name, &args[..], &tps[..], expected, lvalue_pref);
           let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
           let args_err = arg_tys.fold(false, |rest_err, a| rest_err || a.references_error());
           if args_err {
@@ -4137,7 +4105,7 @@ fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     let inh = static_inherited_fields(ccx, &tables);
     let rty = ccx.tcx.node_id_to_type(id);
     let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
-    let declty = fcx.ccx.tcx.lookup_item_type(DefId::local(id)).ty;
+    let declty = fcx.ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(id)).ty;
     check_const_with_ty(&fcx, sp, e, declty);
 }
 
@@ -4148,7 +4116,7 @@ fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // Gather locals in statics (because of block expressions).
     // This is technically unnecessary because locals in static items are forbidden,
     // but prevents type checking from blowing up before const checking can properly
-    // emit a error.
+    // emit an error.
     GatherLocalsVisitor { fcx: fcx }.visit_expr(e);
 
     check_expr_with_hint(fcx, e, declty);
@@ -4226,22 +4194,22 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     fn disr_in_range(ccx: &CrateCtxt,
                      ty: attr::IntType,
                      disr: ty::Disr) -> bool {
-        fn uint_in_range(ccx: &CrateCtxt, ty: hir::UintTy, disr: ty::Disr) -> bool {
+        fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
             match ty {
-                hir::TyU8 => disr as u8 as Disr == disr,
-                hir::TyU16 => disr as u16 as Disr == disr,
-                hir::TyU32 => disr as u32 as Disr == disr,
-                hir::TyU64 => disr as u64 as Disr == disr,
-                hir::TyUs => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
+                ast::TyU8 => disr as u8 as Disr == disr,
+                ast::TyU16 => disr as u16 as Disr == disr,
+                ast::TyU32 => disr as u32 as Disr == disr,
+                ast::TyU64 => disr as u64 as Disr == disr,
+                ast::TyUs => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
             }
         }
-        fn int_in_range(ccx: &CrateCtxt, ty: hir::IntTy, disr: ty::Disr) -> bool {
+        fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
             match ty {
-                hir::TyI8 => disr as i8 as Disr == disr,
-                hir::TyI16 => disr as i16 as Disr == disr,
-                hir::TyI32 => disr as i32 as Disr == disr,
-                hir::TyI64 => disr as i64 as Disr == disr,
-                hir::TyIs => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
+                ast::TyI8 => disr as i8 as Disr == disr,
+                ast::TyI16 => disr as i16 as Disr == disr,
+                ast::TyI32 => disr as i32 as Disr == disr,
+                ast::TyI64 => disr as i64 as Disr == disr,
+                ast::TyIs => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
             }
         }
         match ty {
@@ -4270,7 +4238,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
             }
         }
 
-        let def_id = DefId::local(id);
+        let def_id = ccx.tcx.map.local_def_id(id);
 
         let variants = &ccx.tcx.lookup_adt_def(def_id).variants;
         for (v, variant) in vs.iter().zip(variants.iter()) {
@@ -4281,7 +4249,8 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                 Some(i) => {
                     span_err!(ccx.tcx.sess, v.span, E0081,
                         "discriminant value `{}` already exists", disr_vals[i]);
-                    span_note!(ccx.tcx.sess, ccx.tcx.map.span(variants[i].did.node),
+                    let variant_i_node_id = ccx.tcx.map.as_local_node_id(variants[i].did).unwrap();
+                    span_note!(ccx.tcx.sess, ccx.tcx.map.span(variant_i_node_id),
                         "conflicting discriminant here")
                 }
                 None => {}
@@ -4308,8 +4277,8 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
         }
     }
 
-    let hint = *ccx.tcx.lookup_repr_hints(DefId { krate: LOCAL_CRATE, node: id })
-        .get(0).unwrap_or(&attr::ReprAny);
+    let def_id = ccx.tcx.map.local_def_id(id);
+    let hint = *ccx.tcx.lookup_repr_hints(def_id).get(0).unwrap_or(&attr::ReprAny);
 
     if hint != attr::ReprAny && vs.len() <= 1 {
         if vs.len() == 1 {
@@ -4332,7 +4301,7 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                 defn: def::Def)
                                                 -> (TypeScheme<'tcx>, GenericPredicates<'tcx>) {
     match defn {
-        def::DefLocal(nid) | def::DefUpvar(nid, _, _) => {
+        def::DefLocal(_, nid) | def::DefUpvar(_, nid, _, _) => {
             let typ = fcx.local_ty(sp, nid);
             (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
              ty::GenericPredicates::empty())
@@ -4350,7 +4319,6 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         def::DefMod(..) |
         def::DefForeignMod(..) |
         def::DefUse(..) |
-        def::DefRegion(..) |
         def::DefLabel(..) |
         def::DefSelfTy(..) => {
             fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
@@ -4402,7 +4370,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     //    parameters permitted at present, but perhaps we will allow
     //    them in the future.)
     //
-    // 1b. Reference to a enum variant or tuple-like struct:
+    // 1b. Reference to an enum variant or tuple-like struct:
     //
     //        struct foo<T>(...)
     //        enum E<T> { foo(...) }
@@ -4521,7 +4489,6 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         def::DefForeignMod(..) |
         def::DefLocal(..) |
         def::DefUse(..) |
-        def::DefRegion(..) |
         def::DefLabel(..) |
         def::DefUpvar(..) => {
             segment_spaces = vec![None; segments.len()];
@@ -4953,7 +4920,7 @@ pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         if !*b {
             span_err!(ccx.tcx.sess, span, E0091,
                 "type parameter `{}` is unused",
-                tps[i].ident);
+                tps[i].name);
         }
     }
 }
index 07754e8506b9c907eeccab1431900a5053f02cd1..0c65f68f02e3e8fac792447de3f95495271511d6 100644 (file)
@@ -17,10 +17,8 @@ use super::{
     demand,
     method,
     FnCtxt,
-    structurally_resolved_type,
 };
 use middle::def_id::DefId;
-use middle::traits;
 use middle::ty::{Ty, HasTypeFlags, PreferMutLvalue};
 use syntax::ast;
 use syntax::parse::token;
@@ -34,34 +32,24 @@ pub fn check_binop_assign<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                    lhs_expr: &'tcx hir::Expr,
                                    rhs_expr: &'tcx hir::Expr)
 {
-    let tcx = fcx.ccx.tcx;
-
     check_expr_with_lvalue_pref(fcx, lhs_expr, PreferMutLvalue);
-    check_expr(fcx, rhs_expr);
 
-    let lhs_ty = structurally_resolved_type(fcx, lhs_expr.span, fcx.expr_ty(lhs_expr));
-    let rhs_ty = structurally_resolved_type(fcx, rhs_expr.span, fcx.expr_ty(rhs_expr));
+    let lhs_ty = fcx.resolve_type_vars_if_possible(fcx.expr_ty(lhs_expr));
+    let (rhs_ty, return_ty) =
+        check_overloaded_binop(fcx, expr, lhs_expr, lhs_ty, rhs_expr, op, IsAssign::Yes);
+    let rhs_ty = fcx.resolve_type_vars_if_possible(rhs_ty);
 
-    if is_builtin_binop(lhs_ty, rhs_ty, op) {
+    if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() && is_builtin_binop(lhs_ty, rhs_ty, op) {
         enforce_builtin_binop_types(fcx, lhs_expr, lhs_ty, rhs_expr, rhs_ty, op);
         fcx.write_nil(expr.id);
     } else {
-        // error types are considered "builtin"
-        assert!(!lhs_ty.references_error() || !rhs_ty.references_error());
-        span_err!(tcx.sess, lhs_expr.span, E0368,
-                  "binary assignment operation `{}=` cannot be applied to types `{}` and `{}`",
-                  hir_util::binop_to_string(op.node),
-                  lhs_ty,
-                  rhs_ty);
-        fcx.write_error(expr.id);
+        fcx.write_ty(expr.id, return_ty);
     }
 
     let tcx = fcx.tcx();
     if !tcx.expr_is_lval(lhs_expr) {
         span_err!(tcx.sess, lhs_expr.span, E0067, "invalid left-hand side expression");
     }
-
-    fcx.require_expr_have_sized_type(lhs_expr, traits::AssignmentLhsSized);
 }
 
 /// Check a potentially overloaded binary operator.
@@ -95,7 +83,7 @@ pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             // overloaded. This is the way to be most flexible w/r/t
             // types that get inferred.
             let (rhs_ty, return_ty) =
-                check_overloaded_binop(fcx, expr, lhs_expr, lhs_ty, rhs_expr, op);
+                check_overloaded_binop(fcx, expr, lhs_expr, lhs_ty, rhs_expr, op, IsAssign::No);
 
             // Supply type inference hints if relevant. Probably these
             // hints should be enforced during select as part of the
@@ -167,14 +155,16 @@ fn check_overloaded_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                     lhs_expr: &'tcx hir::Expr,
                                     lhs_ty: Ty<'tcx>,
                                     rhs_expr: &'tcx hir::Expr,
-                                    op: hir::BinOp)
+                                    op: hir::BinOp,
+                                    is_assign: IsAssign)
                                     -> (Ty<'tcx>, Ty<'tcx>)
 {
-    debug!("check_overloaded_binop(expr.id={}, lhs_ty={:?})",
+    debug!("check_overloaded_binop(expr.id={}, lhs_ty={:?}, is_assign={:?})",
            expr.id,
-           lhs_ty);
+           lhs_ty,
+           is_assign);
 
-    let (name, trait_def_id) = name_and_trait_def_id(fcx, op);
+    let (name, trait_def_id) = name_and_trait_def_id(fcx, op, is_assign);
 
     // NB: As we have not yet type-checked the RHS, we don't have the
     // type at hand. Make a variable to represent it. The whole reason
@@ -191,10 +181,38 @@ fn check_overloaded_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         Err(()) => {
             // error types are considered "builtin"
             if !lhs_ty.references_error() {
-                span_err!(fcx.tcx().sess, lhs_expr.span, E0369,
-                          "binary operation `{}` cannot be applied to type `{}`",
-                          hir_util::binop_to_string(op.node),
-                          lhs_ty);
+                if let IsAssign::Yes = is_assign {
+                    span_err!(fcx.tcx().sess, lhs_expr.span, E0368,
+                              "binary assignment operation `{}=` cannot be applied to type `{}`",
+                              hir_util::binop_to_string(op.node),
+                              lhs_ty);
+                } else {
+                    span_err!(fcx.tcx().sess, lhs_expr.span, E0369,
+                              "binary operation `{}` cannot be applied to type `{}`",
+                              hir_util::binop_to_string(op.node),
+                              lhs_ty);
+                    let missing_trait = match op.node {
+                        hir::BiAdd    => Some("std::ops::Add"),
+                        hir::BiSub    => Some("std::ops::Sub"),
+                        hir::BiMul    => Some("std::ops::Mul"),
+                        hir::BiDiv    => Some("std::ops::Div"),
+                        hir::BiRem    => Some("std::ops::Rem"),
+                        hir::BiBitAnd => Some("std::ops::BitAnd"),
+                        hir::BiBitOr  => Some("std::ops::BitOr"),
+                        hir::BiShl    => Some("std::ops::Shl"),
+                        hir::BiShr    => Some("std::ops::Shr"),
+                        hir::BiEq | hir::BiNe => Some("std::cmp::PartialEq"),
+                        hir::BiLt | hir::BiLe | hir::BiGt | hir::BiGe =>
+                            Some("std::cmp::PartialOrd"),
+                        _             => None
+                    };
+
+                    if let Some(missing_trait) = missing_trait {
+                        span_note!(fcx.tcx().sess, lhs_expr.span,
+                                   "an implementation of `{}` might be missing for `{}`",
+                                    missing_trait, lhs_ty);
+                    }
+                }
             }
             fcx.tcx().types.err
         }
@@ -231,27 +249,51 @@ pub fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     }
 }
 
-fn name_and_trait_def_id(fcx: &FnCtxt, op: hir::BinOp) -> (&'static str, Option<DefId>) {
+fn name_and_trait_def_id(fcx: &FnCtxt,
+                         op: hir::BinOp,
+                         is_assign: IsAssign)
+                         -> (&'static str, Option<DefId>) {
     let lang = &fcx.tcx().lang_items;
-    match op.node {
-        hir::BiAdd => ("add", lang.add_trait()),
-        hir::BiSub => ("sub", lang.sub_trait()),
-        hir::BiMul => ("mul", lang.mul_trait()),
-        hir::BiDiv => ("div", lang.div_trait()),
-        hir::BiRem => ("rem", lang.rem_trait()),
-        hir::BiBitXor => ("bitxor", lang.bitxor_trait()),
-        hir::BiBitAnd => ("bitand", lang.bitand_trait()),
-        hir::BiBitOr => ("bitor", lang.bitor_trait()),
-        hir::BiShl => ("shl", lang.shl_trait()),
-        hir::BiShr => ("shr", lang.shr_trait()),
-        hir::BiLt => ("lt", lang.ord_trait()),
-        hir::BiLe => ("le", lang.ord_trait()),
-        hir::BiGe => ("ge", lang.ord_trait()),
-        hir::BiGt => ("gt", lang.ord_trait()),
-        hir::BiEq => ("eq", lang.eq_trait()),
-        hir::BiNe => ("ne", lang.eq_trait()),
-        hir::BiAnd | hir::BiOr => {
-            fcx.tcx().sess.span_bug(op.span, "&& and || are not overloadable")
+
+    if let IsAssign::Yes = is_assign {
+        match op.node {
+            hir::BiAdd => ("add_assign", lang.add_assign_trait()),
+            hir::BiSub => ("sub_assign", lang.sub_assign_trait()),
+            hir::BiMul => ("mul_assign", lang.mul_assign_trait()),
+            hir::BiDiv => ("div_assign", lang.div_assign_trait()),
+            hir::BiRem => ("rem_assign", lang.rem_assign_trait()),
+            hir::BiBitXor => ("bitxor_assign", lang.bitxor_assign_trait()),
+            hir::BiBitAnd => ("bitand_assign", lang.bitand_assign_trait()),
+            hir::BiBitOr => ("bitor_assign", lang.bitor_assign_trait()),
+            hir::BiShl => ("shl_assign", lang.shl_assign_trait()),
+            hir::BiShr => ("shr_assign", lang.shr_assign_trait()),
+            hir::BiLt | hir::BiLe | hir::BiGe | hir::BiGt | hir::BiEq | hir::BiNe | hir::BiAnd |
+            hir::BiOr => {
+                fcx.tcx().sess.span_bug(op.span, &format!("impossible assignment operation: {}=",
+                                        hir_util::binop_to_string(op.node)))
+            }
+        }
+    } else {
+        match op.node {
+            hir::BiAdd => ("add", lang.add_trait()),
+            hir::BiSub => ("sub", lang.sub_trait()),
+            hir::BiMul => ("mul", lang.mul_trait()),
+            hir::BiDiv => ("div", lang.div_trait()),
+            hir::BiRem => ("rem", lang.rem_trait()),
+            hir::BiBitXor => ("bitxor", lang.bitxor_trait()),
+            hir::BiBitAnd => ("bitand", lang.bitand_trait()),
+            hir::BiBitOr => ("bitor", lang.bitor_trait()),
+            hir::BiShl => ("shl", lang.shl_trait()),
+            hir::BiShr => ("shr", lang.shr_trait()),
+            hir::BiLt => ("lt", lang.ord_trait()),
+            hir::BiLe => ("le", lang.ord_trait()),
+            hir::BiGe => ("ge", lang.ord_trait()),
+            hir::BiGt => ("gt", lang.ord_trait()),
+            hir::BiEq => ("eq", lang.eq_trait()),
+            hir::BiNe => ("ne", lang.eq_trait()),
+            hir::BiAnd | hir::BiOr => {
+                fcx.tcx().sess.span_bug(op.span, "&& and || are not overloadable")
+            }
         }
     }
 }
@@ -362,6 +404,13 @@ impl BinOpCategory {
     }
 }
 
+/// Whether the binary operation is an assignment (`a += b`), or not (`a + b`)
+#[derive(Clone, Copy, Debug)]
+enum IsAssign {
+    No,
+    Yes,
+}
+
 /// Returns true if this is a built-in arithmetic operation (e.g. u32
 /// + u32, i16x4 == i16x4) and false if these types would have to be
 /// overloaded to be legal. There are two reasons that we distinguish
index 155caaa8cb0fe2a7f4f1fac3b1d6bb3bde5540a2..7c6417e61d464de18791032f8d885a9f5b503855 100644 (file)
@@ -77,7 +77,7 @@
 //! borrowed pointer? I mean any data that is reached by first
 //! dereferencing a borrowed pointer and then either traversing
 //! interior offsets or boxes.  We say that the guarantor
-//! of such data it the region of the borrowed pointer that was
+//! of such data is the region of the borrowed pointer that was
 //! traversed.  This is essentially the same as the ownership
 //! relation, except that a borrowed pointer never owns its
 //! contents.
@@ -592,6 +592,8 @@ fn visit_expr(rcx: &mut Rcx, expr: &hir::Expr) {
         };
 
         substs_wf_in_scope(rcx, origin, &callee.substs, expr.span, expr_region);
+        type_must_outlive(rcx, infer::ExprTypeIsNotInScope(callee.ty, expr.span),
+                          callee.ty, expr_region);
     }
 
     // Check any autoderefs or autorefs that appear.
@@ -664,6 +666,8 @@ fn visit_expr(rcx: &mut Rcx, expr: &hir::Expr) {
         }
     }
 
+    debug!("regionck::visit_expr(e={:?}, repeating_scope={}) - visiting subexprs",
+           expr, rcx.repeating_scope);
     match expr.node {
         hir::ExprPath(..) => {
             rcx.fcx.opt_node_ty_substs(expr.id, |item_substs| {
@@ -695,7 +699,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &hir::Expr) {
         hir::ExprAssignOp(_, ref lhs, ref rhs) => {
             if has_method_map {
                 constrain_call(rcx, expr, Some(&**lhs),
-                               Some(&**rhs).into_iter(), true);
+                               Some(&**rhs).into_iter(), false);
             }
 
             visit::walk_expr(rcx, expr);
@@ -1178,9 +1182,10 @@ fn link_fn_args(rcx: &Rcx, body_scope: CodeExtent, args: &[hir::Arg]) {
         let arg_ty = rcx.fcx.node_ty(arg.id);
         let re_scope = ty::ReScope(body_scope);
         let arg_cmt = mc.cat_rvalue(arg.id, arg.ty.span, re_scope, arg_ty);
-        debug!("arg_ty={:?} arg_cmt={:?}",
+        debug!("arg_ty={:?} arg_cmt={:?} arg={:?}",
                arg_ty,
-               arg_cmt);
+               arg_cmt,
+               arg);
         link_pattern(rcx, mc, arg_cmt, &*arg.pat);
     }
 }
@@ -1523,9 +1528,10 @@ pub fn type_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
 {
     let ty = rcx.resolve_type(ty);
 
-    debug!("type_must_outlive(ty={:?}, region={:?})",
+    debug!("type_must_outlive(ty={:?}, region={:?}, origin={:?})",
            ty,
-           region);
+           region,
+           origin);
 
     assert!(!ty.has_escaping_regions());
 
index 10d7c4620e7d3ffbb92e7cd0ebebbae368476919..78d493c8a711cb9ca2acb474f66fe800adde4e46 100644 (file)
@@ -43,7 +43,6 @@
 use super::FnCtxt;
 
 use check::demand;
-use middle::def_id::DefId;
 use middle::expr_use_visitor as euv;
 use middle::mem_categorization as mc;
 use middle::ty::{self, Ty};
@@ -130,7 +129,7 @@ impl<'a,'tcx> SeedBorrowKind<'a,'tcx> {
                      capture_clause: hir::CaptureClause,
                      _body: &hir::Block)
     {
-        let closure_def_id = DefId::local(expr.id);
+        let closure_def_id = self.tcx().map.local_def_id(expr.id);
         if !self.fcx.inh.tables.borrow().closure_kinds.contains_key(&closure_def_id) {
             self.closures_with_inferred_kinds.insert(expr.id);
             self.fcx.inh.tables.borrow_mut().closure_kinds
@@ -141,7 +140,7 @@ impl<'a,'tcx> SeedBorrowKind<'a,'tcx> {
 
         self.tcx().with_freevars(expr.id, |freevars| {
             for freevar in freevars {
-                let var_node_id = freevar.def.local_node_id();
+                let var_node_id = freevar.def.var_id();
                 let upvar_id = ty::UpvarId { var_id: var_node_id,
                                              closure_expr_id: expr.id };
                 debug!("seed upvar_id {:?}", upvar_id);
@@ -229,7 +228,7 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> {
 
         // Now we must process and remove any deferred resolutions,
         // since we have a concrete closure kind.
-        let closure_def_id = DefId::local(id);
+        let closure_def_id = self.fcx.tcx().map.local_def_id(id);
         if self.closures_with_inferred_kinds.contains(&id) {
             let mut deferred_call_resolutions =
                 self.fcx.remove_deferred_call_resolutions(closure_def_id);
@@ -250,16 +249,16 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> {
         tcx.with_freevars(closure_id, |freevars| {
             freevars.iter()
                     .map(|freevar| {
-                        let freevar_def_id = freevar.def.def_id();
-                        let freevar_ty = self.fcx.node_ty(freevar_def_id.node);
+                        let freevar_node_id = freevar.def.var_id();
+                        let freevar_ty = self.fcx.node_ty(freevar_node_id);
                         let upvar_id = ty::UpvarId {
-                            var_id: freevar_def_id.node,
+                            var_id: freevar_node_id,
                             closure_expr_id: closure_id
                         };
                         let capture = self.fcx.infcx().upvar_capture(upvar_id).unwrap();
 
-                        debug!("freevar_def_id={:?} freevar_ty={:?} capture={:?}",
-                               freevar_def_id, freevar_ty, capture);
+                        debug!("freevar_node_id={:?} freevar_ty={:?} capture={:?}",
+                               freevar_node_id, freevar_ty, capture);
 
                         match capture {
                             ty::UpvarCapture::ByValue => freevar_ty,
@@ -483,7 +482,7 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> {
             return;
         }
 
-        let closure_def_id = DefId::local(closure_id);
+        let closure_def_id = self.fcx.tcx().map.local_def_id(closure_id);
         let closure_kinds = &mut self.fcx.inh.tables.borrow_mut().closure_kinds;
         let existing_kind = *closure_kinds.get(&closure_def_id).unwrap();
 
index 2c931e7830d59ba04b9f1eb28899acda39865738..e41b4de7ba1fd657f9b9c855676d60586b204011 100644 (file)
@@ -12,7 +12,6 @@ use astconv::AstConv;
 use check::{FnCtxt, Inherited, blank_fn_ctxt, regionck, wfcheck};
 use constrained_type_params::{identify_constrained_type_params, Parameter};
 use CrateCtxt;
-use middle::def_id::DefId;
 use middle::region;
 use middle::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace};
 use middle::traits;
@@ -55,9 +54,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     /// the types first.
     fn check_item_well_formed(&mut self, item: &hir::Item) {
         let ccx = self.ccx;
-        debug!("check_item_well_formed(it.id={}, it.ident={})",
+        debug!("check_item_well_formed(it.id={}, it.name={})",
                item.id,
-               ccx.tcx.item_path_str(DefId::local(item.id)));
+               ccx.tcx.item_path_str(ccx.tcx.map.local_def_id(item.id)));
 
         match item.node {
             /// Right now we check that every default trait implementation
@@ -81,7 +80,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                 self.check_impl(item);
             }
             hir::ItemImpl(_, hir::ImplPolarity::Negative, _, Some(_), _, _) => {
-                let trait_ref = ccx.tcx.impl_trait_ref(DefId::local(item.id)).unwrap();
+                let item_def_id = ccx.tcx.map.local_def_id(item.id);
+                let trait_ref = ccx.tcx.impl_trait_ref(item_def_id).unwrap();
                 ccx.tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id);
                 match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
                     Some(ty::BoundSend) | Some(ty::BoundSync) => {}
@@ -103,7 +103,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
             }
             hir::ItemStruct(ref struct_def, ref ast_generics) => {
                 self.check_type_defn(item, |fcx| {
-                    vec![struct_variant(fcx, &**struct_def)]
+                    vec![struct_variant(fcx, struct_def)]
                 });
 
                 self.check_variances_for_type_defn(item, ast_generics);
@@ -117,9 +117,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
             }
             hir::ItemTrait(_, _, _, ref items) => {
                 let trait_predicates =
-                    ccx.tcx.lookup_predicates(DefId::local(item.id));
+                    ccx.tcx.lookup_predicates(ccx.tcx.map.local_def_id(item.id));
                 reject_non_type_param_bounds(ccx.tcx, item.span, &trait_predicates);
-                if ccx.tcx.trait_has_default_impl(DefId::local(item.id)) {
+                if ccx.tcx.trait_has_default_impl(ccx.tcx.map.local_def_id(item.id)) {
                     if !items.is_empty() {
                         wfcheck::error_380(ccx, item.span);
                     }
@@ -133,7 +133,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
         F: for<'fcx> FnMut(&mut CheckTypeWellFormedVisitor<'ccx, 'tcx>, &FnCtxt<'fcx, 'tcx>),
     {
         let ccx = self.ccx;
-        let item_def_id = DefId::local(item.id);
+        let item_def_id = ccx.tcx.map.local_def_id(item.id);
         let type_scheme = ccx.tcx.lookup_item_type(item_def_id);
         let type_predicates = ccx.tcx.lookup_predicates(item_def_id);
         reject_non_type_param_bounds(ccx.tcx, item.span, &type_predicates);
@@ -194,7 +194,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                                                         Some(&mut this.cache));
             debug!("check_item_type at bounds_checker.scope: {:?}", bounds_checker.scope);
 
-            let type_scheme = fcx.tcx().lookup_item_type(DefId::local(item.id));
+            let item_def_id = fcx.tcx().map.local_def_id(item.id);
+            let type_scheme = fcx.tcx().lookup_item_type(item_def_id);
             let item_ty = fcx.instantiate_type_scheme(item.span,
                                                       &fcx.inh
                                                           .infcx
@@ -230,7 +231,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
 
             // Similarly, obtain an "inside" reference to the trait
             // that the impl implements.
-            let trait_ref = match fcx.tcx().impl_trait_ref(DefId::local(item.id)) {
+            let trait_ref = match fcx.tcx().impl_trait_ref(fcx.tcx().map.local_def_id(item.id)) {
                 None => { return; }
                 Some(t) => { t }
             };
@@ -279,7 +280,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                                      item: &hir::Item,
                                      ast_generics: &hir::Generics)
     {
-        let item_def_id = DefId::local(item.id);
+        let item_def_id = self.tcx().map.local_def_id(item.id);
         let ty_predicates = self.tcx().lookup_predicates(item_def_id);
         let variances = self.tcx().item_variances(item_def_id);
 
@@ -324,7 +325,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                 -> ty::ParamTy
     {
         let name = match space {
-            TypeSpace => ast_generics.ty_params[index].ident.name,
+            TypeSpace => ast_generics.ty_params[index].name,
             SelfSpace => special_idents::type_self.name,
             FnSpace => self.tcx().sess.bug("Fn space occupied?"),
         };
@@ -431,7 +432,7 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
         match fk {
             FnKind::Closure | FnKind::ItemFn(..) => {}
             FnKind::Method(..) => {
-                match self.tcx().impl_or_trait_item(DefId::local(id)) {
+                match self.tcx().impl_or_trait_item(self.tcx().map.local_def_id(id)) {
                     ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
                         reject_shadowing_type_parameters(self.tcx(), span, &ty_method.generics)
                     }
@@ -444,7 +445,7 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
 
     fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) {
         if let hir::MethodTraitItem(_, None) = trait_item.node {
-            match self.tcx().impl_or_trait_item(DefId::local(trait_item.id)) {
+            match self.tcx().impl_or_trait_item(self.tcx().map.local_def_id(trait_item.id)) {
                 ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
                     reject_non_type_param_bounds(
                         self.tcx(),
@@ -623,11 +624,10 @@ struct AdtField<'tcx> {
 }
 
 fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                            struct_def: &hir::StructDef)
+                            struct_def: &hir::VariantData)
                             -> AdtVariant<'tcx> {
     let fields =
-        struct_def.fields
-        .iter()
+        struct_def.fields().iter()
         .map(|field| {
             let field_ty = fcx.tcx().node_id_to_type(field.node.id);
             let field_ty = fcx.instantiate_type_scheme(field.span,
@@ -646,41 +646,7 @@ fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                            enum_def: &hir::EnumDef)
                            -> Vec<AdtVariant<'tcx>> {
     enum_def.variants.iter()
-        .map(|variant| {
-            match variant.node.kind {
-                hir::TupleVariantKind(ref args) if !args.is_empty() => {
-                    let ctor_ty = fcx.tcx().node_id_to_type(variant.node.id);
-
-                    // the regions in the argument types come from the
-                    // enum def'n, and hence will all be early bound
-                    let arg_tys = fcx.tcx().no_late_bound_regions(&ctor_ty.fn_args()).unwrap();
-                    AdtVariant {
-                        fields: args.iter().enumerate().map(|(index, arg)| {
-                            let arg_ty = arg_tys[index];
-                            let arg_ty =
-                                fcx.instantiate_type_scheme(variant.span,
-                                                            &fcx.inh
-                                                                .infcx
-                                                                .parameter_environment
-                                                                .free_substs,
-                                                            &arg_ty);
-                            AdtField {
-                                ty: arg_ty,
-                                span: arg.ty.span
-                            }
-                        }).collect()
-                    }
-                }
-                hir::TupleVariantKind(_) => {
-                    AdtVariant {
-                        fields: Vec::new()
-                    }
-                }
-                hir::StructVariantKind(ref struct_def) => {
-                    struct_variant(fcx, &**struct_def)
-                }
-            }
-        })
+        .map(|variant| struct_variant(fcx, &variant.node.data))
         .collect()
 }
 
index 06dd80c57ada8132094e6880f044dd65c3c43d19..ab091472d2ca3957d5a87e564deca8d52478fc46 100644 (file)
@@ -61,9 +61,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     /// the types first.
     fn check_item_well_formed(&mut self, item: &hir::Item) {
         let ccx = self.ccx;
-        debug!("check_item_well_formed(it.id={}, it.ident={})",
+        debug!("check_item_well_formed(it.id={}, it.name={})",
                item.id,
-               ccx.tcx.item_path_str(DefId::local(item.id)));
+               ccx.tcx.item_path_str(ccx.tcx.map.local_def_id(item.id)));
 
         match item.node {
             /// Right now we check that every default trait implementation
@@ -90,7 +90,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
             hir::ItemImpl(_, hir::ImplPolarity::Negative, _, Some(_), _, _) => {
                 // FIXME(#27579) what amount of WF checking do we need for neg impls?
 
-                let trait_ref = ccx.tcx.impl_trait_ref(DefId::local(item.id)).unwrap();
+                let trait_ref = ccx.tcx.impl_trait_ref(ccx.tcx.map.local_def_id(item.id)).unwrap();
                 ccx.tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id);
                 match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
                     Some(ty::BoundSend) | Some(ty::BoundSync) => {}
@@ -112,7 +112,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
             }
             hir::ItemStruct(ref struct_def, ref ast_generics) => {
                 self.check_type_defn(item, |fcx| {
-                    vec![struct_variant(fcx, &**struct_def)]
+                    vec![struct_variant(fcx, struct_def)]
                 });
 
                 self.check_variances_for_type_defn(item, ast_generics);
@@ -137,7 +137,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
             let free_substs = &fcx.inh.infcx.parameter_environment.free_substs;
             let free_id = fcx.inh.infcx.parameter_environment.free_id;
 
-            let item = fcx.tcx().impl_or_trait_item(DefId::local(item_id));
+            let item = fcx.tcx().impl_or_trait_item(fcx.tcx().map.local_def_id(item_id));
 
             let mut implied_bounds = match item.container() {
                 ty::TraitContainer(_) => vec![],
@@ -216,7 +216,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
             }
 
             let free_substs = &fcx.inh.infcx.parameter_environment.free_substs;
-            let predicates = fcx.tcx().lookup_predicates(DefId::local(item.id));
+            let predicates = fcx.tcx().lookup_predicates(fcx.tcx().map.local_def_id(item.id));
             let predicates = fcx.instantiate_bounds(item.span, free_substs, &predicates);
             this.check_where_clauses(fcx, item.span, &predicates);
 
@@ -228,7 +228,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                    item: &hir::Item,
                    items: &[P<hir::TraitItem>])
     {
-        let trait_def_id = DefId::local(item.id);
+        let trait_def_id = self.tcx().map.local_def_id(item.id);
 
         if self.ccx.tcx.trait_has_default_impl(trait_def_id) {
             if !items.is_empty() {
@@ -251,7 +251,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     {
         self.with_item_fcx(item, |fcx, this| {
             let free_substs = &fcx.inh.infcx.parameter_environment.free_substs;
-            let type_scheme = fcx.tcx().lookup_item_type(DefId::local(item.id));
+            let type_scheme = fcx.tcx().lookup_item_type(fcx.tcx().map.local_def_id(item.id));
             let item_ty = fcx.instantiate_type_scheme(item.span, free_substs, &type_scheme.ty);
             let bare_fn_ty = match item_ty.sty {
                 ty::TyBareFn(_, ref bare_fn_ty) => bare_fn_ty,
@@ -260,7 +260,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                 }
             };
 
-            let predicates = fcx.tcx().lookup_predicates(DefId::local(item.id));
+            let predicates = fcx.tcx().lookup_predicates(fcx.tcx().map.local_def_id(item.id));
             let predicates = fcx.instantiate_bounds(item.span, free_substs, &predicates);
 
             let mut implied_bounds = vec![];
@@ -276,7 +276,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
         debug!("check_item_type: {:?}", item);
 
         self.with_item_fcx(item, |fcx, this| {
-            let type_scheme = fcx.tcx().lookup_item_type(DefId::local(item.id));
+            let type_scheme = fcx.tcx().lookup_item_type(fcx.tcx().map.local_def_id(item.id));
             let item_ty = fcx.instantiate_type_scheme(item.span,
                                                       &fcx.inh
                                                           .infcx
@@ -299,7 +299,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
 
         self.with_item_fcx(item, |fcx, this| {
             let free_substs = &fcx.inh.infcx.parameter_environment.free_substs;
-            let item_def_id = DefId::local(item.id);
+            let item_def_id = fcx.tcx().map.local_def_id(item.id);
 
             match *ast_trait_ref {
                 Some(ref ast_trait_ref) => {
@@ -328,7 +328,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
             let predicates = fcx.instantiate_bounds(item.span, free_substs, &predicates);
             this.check_where_clauses(fcx, item.span, &predicates);
 
-            impl_implied_bounds(fcx, DefId::local(item.id), item.span)
+            impl_implied_bounds(fcx, fcx.tcx().map.local_def_id(item.id), item.span)
         });
     }
 
@@ -386,7 +386,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                                      item: &hir::Item,
                                      ast_generics: &hir::Generics)
     {
-        let item_def_id = DefId::local(item.id);
+        let item_def_id = self.tcx().map.local_def_id(item.id);
         let ty_predicates = self.tcx().lookup_predicates(item_def_id);
         let variances = self.tcx().item_variances(item_def_id);
 
@@ -431,7 +431,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                 -> ty::ParamTy
     {
         let name = match space {
-            TypeSpace => ast_generics.ty_params[index].ident.name,
+            TypeSpace => ast_generics.ty_params[index].name,
             SelfSpace => special_idents::type_self.name,
             FnSpace => self.tcx().sess.bug("Fn space occupied?"),
         };
@@ -521,11 +521,10 @@ struct AdtField<'tcx> {
 }
 
 fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                            struct_def: &hir::StructDef)
+                            struct_def: &hir::VariantData)
                             -> AdtVariant<'tcx> {
     let fields =
-        struct_def.fields
-        .iter()
+        struct_def.fields().iter()
         .map(|field| {
             let field_ty = fcx.tcx().node_id_to_type(field.node.id);
             let field_ty = fcx.instantiate_type_scheme(field.span,
@@ -544,41 +543,7 @@ fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                            enum_def: &hir::EnumDef)
                            -> Vec<AdtVariant<'tcx>> {
     enum_def.variants.iter()
-        .map(|variant| {
-            match variant.node.kind {
-                hir::TupleVariantKind(ref args) if !args.is_empty() => {
-                    let ctor_ty = fcx.tcx().node_id_to_type(variant.node.id);
-
-                    // the regions in the argument types come from the
-                    // enum def'n, and hence will all be early bound
-                    let arg_tys = fcx.tcx().no_late_bound_regions(&ctor_ty.fn_args()).unwrap();
-                    AdtVariant {
-                        fields: args.iter().enumerate().map(|(index, arg)| {
-                            let arg_ty = arg_tys[index];
-                            let arg_ty =
-                                fcx.instantiate_type_scheme(variant.span,
-                                                            &fcx.inh
-                                                                .infcx
-                                                                .parameter_environment
-                                                                .free_substs,
-                                                            &arg_ty);
-                            AdtField {
-                                ty: arg_ty,
-                                span: arg.ty.span
-                            }
-                        }).collect()
-                    }
-                }
-                hir::TupleVariantKind(_) => {
-                    AdtVariant {
-                        fields: Vec::new()
-                    }
-                }
-                hir::StructVariantKind(ref struct_def) => {
-                    struct_variant(fcx, &**struct_def)
-                }
-            }
-        })
+        .map(|variant| struct_variant(fcx, &variant.node.data))
         .collect()
 }
 
index 6f8e064c9d8195c3e98c83affec70b55b00a031c..2c18a245159cffbfe5924fb3db0417f76588b896 100644 (file)
@@ -17,7 +17,7 @@ use astconv::AstConv;
 use check::FnCtxt;
 use middle::def_id::DefId;
 use middle::pat_util;
-use middle::ty::{self, Ty, MethodCall, MethodCallee};
+use middle::ty::{self, Ty, MethodCall, MethodCallee, HasTypeFlags};
 use middle::ty::adjustment;
 use middle::ty::fold::{TypeFolder,TypeFoldable};
 use middle::infer;
@@ -91,24 +91,53 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
     // we observe that something like `a+b` is (known to be)
     // operating on scalars, we clear the overload.
     fn fix_scalar_binary_expr(&mut self, e: &hir::Expr) {
-        if let hir::ExprBinary(ref op, ref lhs, ref rhs) = e.node {
-            let lhs_ty = self.fcx.node_ty(lhs.id);
-            let lhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&lhs_ty);
-
-            let rhs_ty = self.fcx.node_ty(rhs.id);
-            let rhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&rhs_ty);
-
-            if lhs_ty.is_scalar() && rhs_ty.is_scalar() {
-                self.fcx.inh.tables.borrow_mut().method_map.remove(&MethodCall::expr(e.id));
-
-                // weird but true: the by-ref binops put an
-                // adjustment on the lhs but not the rhs; the
-                // adjustment for rhs is kind of baked into the
-                // system.
-                if !hir_util::is_by_value_binop(op.node) {
-                    self.fcx.inh.tables.borrow_mut().adjustments.remove(&lhs.id);
+        match e.node {
+            hir::ExprBinary(ref op, ref lhs, ref rhs) |
+            hir::ExprAssignOp(ref op, ref lhs, ref rhs) => {
+                let lhs_ty = self.fcx.node_ty(lhs.id);
+                let lhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&lhs_ty);
+
+                let rhs_ty = self.fcx.node_ty(rhs.id);
+                let rhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&rhs_ty);
+
+                if lhs_ty.is_scalar() && rhs_ty.is_scalar() {
+                    self.fcx.inh.tables.borrow_mut().method_map.remove(&MethodCall::expr(e.id));
+
+                    // weird but true: the by-ref binops put an
+                    // adjustment on the lhs but not the rhs; the
+                    // adjustment for rhs is kind of baked into the
+                    // system.
+                    match e.node {
+                        hir::ExprBinary(..) => {
+                            if !hir_util::is_by_value_binop(op.node) {
+                                self.fcx.inh.tables.borrow_mut().adjustments.remove(&lhs.id);
+                            }
+                        },
+                        hir::ExprAssignOp(..) => {
+                            self.fcx.inh.tables.borrow_mut().adjustments.remove(&lhs.id);
+                        },
+                        _ => {},
+                    }
+                } else {
+                    let tcx = self.tcx();
+
+                    if let hir::ExprAssignOp(..) = e.node {
+                        if
+                            !tcx.sess.features.borrow().augmented_assignments &&
+                            !self.fcx.expr_ty(e).references_error()
+                        {
+                            tcx.sess.span_err(
+                                e.span,
+                                "overloaded augmented assignments are not stable");
+                            fileline_help!(
+                                tcx.sess, e.span,
+                                "add #![feature(augmented_assignments)] to the crate root \
+                                 to enable");
+                        }
+                    }
                 }
             }
+            _ => {},
         }
     }
 }
@@ -196,6 +225,10 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
                 self.visit_ty(&**ty);
                 write_ty_to_tcx(self.tcx(), count_expr.id, self.tcx().types.usize);
             }
+            hir::TyBareFn(ref function_declaration) => {
+                visit::walk_fn_decl_nopat(self, &function_declaration.decl);
+                walk_list!(self, visit_lifetime_def, &function_declaration.lifetimes);
+            }
             _ => visit::walk_ty(self, t)
         }
     }
@@ -355,8 +388,8 @@ impl ResolveReason {
                 tcx.expr_span(upvar_id.closure_expr_id)
             }
             ResolvingClosure(did) => {
-                if did.is_local() {
-                    tcx.expr_span(did.node)
+                if let Some(node_id) = tcx.map.as_local_node_id(did) {
+                    tcx.expr_span(node_id)
                 } else {
                     DUMMY_SP
                 }
index 8cffac67321f5e1ebf4d33fa45a29d0237df2b0f..b3ec10a8941dc753e69b3f72344cecfbdb2ba5bd 100644 (file)
 // mappings. That mapping code resides here.
 
 
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::DefId;
 use middle::lang_items::UnsizeTraitLangItem;
 use middle::subst::{self, Subst};
 use middle::traits;
 use middle::ty;
 use middle::ty::RegionEscape;
-use middle::ty::{ImplContainer, ImplOrTraitItemId, ConstTraitItemId};
+use middle::ty::{ImplOrTraitItemId, ConstTraitItemId};
 use middle::ty::{MethodTraitItemId, TypeTraitItemId, ParameterEnvironment};
 use middle::ty::{Ty, TyBool, TyChar, TyEnum, TyError};
-use middle::ty::{TyParam, TypeScheme, TyRawPtr};
+use middle::ty::{TyParam, TyRawPtr};
 use middle::ty::{TyRef, TyStruct, TyTrait, TyTuple};
 use middle::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt};
 use middle::ty::{TyUint, TyClosure, TyBox, TyBareFn};
@@ -138,7 +138,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
 
     fn check_implementation(&self, item: &Item) {
         let tcx = self.crate_context.tcx;
-        let impl_did = DefId::local(item.id);
+        let impl_did = tcx.map.local_def_id(item.id);
         let self_type = tcx.lookup_item_type(impl_did);
 
         // If there are no traits, then this implementation must have a
@@ -149,7 +149,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
         if let Some(trait_ref) = self.crate_context.tcx.impl_trait_ref(impl_did) {
             debug!("(checking implementation) adding impl for trait '{:?}', item '{}'",
                    trait_ref,
-                   item.ident);
+                   item.name);
 
             enforce_trait_manually_implementable(self.crate_context.tcx,
                                                  item.span,
@@ -168,65 +168,6 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
         tcx.impl_items.borrow_mut().insert(impl_did, impl_items);
     }
 
-    // Creates default method IDs and performs type substitutions for an impl
-    // and trait pair. Then, for each provided method in the trait, inserts a
-    // `ProvidedMethodInfo` instance into the `provided_method_sources` map.
-    fn instantiate_default_methods(
-            &self,
-            impl_id: DefId,
-            trait_ref: &ty::TraitRef<'tcx>,
-            all_impl_items: &mut Vec<ImplOrTraitItemId>) {
-        let tcx = self.crate_context.tcx;
-        debug!("instantiate_default_methods(impl_id={:?}, trait_ref={:?})",
-               impl_id, trait_ref);
-
-        let impl_type_scheme = tcx.lookup_item_type(impl_id);
-
-        let prov = tcx.provided_trait_methods(trait_ref.def_id);
-        for trait_method in &prov {
-            // Synthesize an ID.
-            let new_id = tcx.sess.next_node_id();
-            let new_did = DefId::local(new_id);
-
-            debug!("new_did={:?} trait_method={:?}", new_did, trait_method);
-
-            // Create substitutions for the various trait parameters.
-            let new_method_ty =
-                Rc::new(subst_receiver_types_in_method_ty(
-                    tcx,
-                    impl_id,
-                    &impl_type_scheme,
-                    trait_ref,
-                    new_did,
-                    &**trait_method,
-                    Some(trait_method.def_id)));
-
-            debug!("new_method_ty={:?}", new_method_ty);
-            all_impl_items.push(MethodTraitItemId(new_did));
-
-            // construct the polytype for the method based on the
-            // method_ty.  it will have all the generics from the
-            // impl, plus its own.
-            let new_polytype = ty::TypeScheme {
-                generics: new_method_ty.generics.clone(),
-                ty: tcx.mk_fn(Some(new_did),
-                              tcx.mk_bare_fn(new_method_ty.fty.clone()))
-            };
-            debug!("new_polytype={:?}", new_polytype);
-
-            tcx.register_item_type(new_did, new_polytype);
-            tcx.predicates.borrow_mut().insert(new_did, new_method_ty.predicates.clone());
-            tcx.impl_or_trait_items
-               .borrow_mut()
-               .insert(new_did, ty::MethodTraitItem(new_method_ty));
-
-            // Pair the new synthesized ID up with the
-            // ID of the method.
-            self.crate_context.tcx.provided_method_sources.borrow_mut()
-                .insert(new_did, trait_method.def_id);
-        }
-    }
-
     fn add_inherent_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
         match self.inherent_impls.borrow().get(&base_def_id) {
             Some(implementation_list) => {
@@ -252,27 +193,20 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
     fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
         match item.node {
             ItemImpl(_, _, _, _, _, ref impl_items) => {
-                let mut items: Vec<ImplOrTraitItemId> =
-                        impl_items.iter().map(|impl_item| {
+                impl_items.iter().map(|impl_item| {
+                    let impl_def_id = self.crate_context.tcx.map.local_def_id(impl_item.id);
                     match impl_item.node {
                         hir::ConstImplItem(..) => {
-                            ConstTraitItemId(DefId::local(impl_item.id))
+                            ConstTraitItemId(impl_def_id)
                         }
                         hir::MethodImplItem(..) => {
-                            MethodTraitItemId(DefId::local(impl_item.id))
+                            MethodTraitItemId(impl_def_id)
                         }
                         hir::TypeImplItem(_) => {
-                            TypeTraitItemId(DefId::local(impl_item.id))
+                            TypeTraitItemId(impl_def_id)
                         }
                     }
-                }).collect();
-
-                let def_id = DefId::local(item.id);
-                if let Some(trait_ref) = self.crate_context.tcx.impl_trait_ref(def_id) {
-                    self.instantiate_default_methods(def_id, &trait_ref, &mut items);
-                }
-
-                items
+                }).collect()
             }
             _ => {
                 self.crate_context.tcx.sess.span_bug(item.span,
@@ -312,17 +246,15 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                 }
                 _ => {
                     // Destructors only work on nominal types.
-                    if impl_did.is_local() {
-                        {
-                            match tcx.map.find(impl_did.node) {
-                                Some(hir_map::NodeItem(item)) => {
-                                    span_err!(tcx.sess, item.span, E0120,
-                                        "the Drop trait may only be implemented on structures");
-                                }
-                                _ => {
-                                    tcx.sess.bug("didn't find impl in ast \
-                                                  map");
-                                }
+                    if let Some(impl_node_id) = tcx.map.as_local_node_id(impl_did) {
+                        match tcx.map.find(impl_node_id) {
+                            Some(hir_map::NodeItem(item)) => {
+                                span_err!(tcx.sess, item.span, E0120,
+                                          "the Drop trait may only be implemented on structures");
+                            }
+                            _ => {
+                                tcx.sess.bug("didn't find impl in ast \
+                                              map");
                             }
                         }
                     } else {
@@ -348,18 +280,20 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             debug!("check_implementations_of_copy: impl_did={:?}",
                    impl_did);
 
-            if impl_did.krate != LOCAL_CRATE {
+            let impl_node_id = if let Some(n) = tcx.map.as_local_node_id(impl_did) {
+                n
+            } else {
                 debug!("check_implementations_of_copy(): impl not in this \
                         crate");
                 return
-            }
+            };
 
             let self_type = tcx.lookup_item_type(impl_did);
             debug!("check_implementations_of_copy: self_type={:?} (bound)",
                    self_type);
 
-            let span = tcx.map.span(impl_did.node);
-            let param_env = ParameterEnvironment::for_item(tcx, impl_did.node);
+            let span = tcx.map.span(impl_node_id);
+            let param_env = ParameterEnvironment::for_item(tcx, impl_node_id);
             let self_type = self_type.ty.subst(tcx, &param_env.free_substs);
             assert!(!self_type.has_escaping_regions());
 
@@ -417,11 +351,13 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             debug!("check_implementations_of_coerce_unsized: impl_did={:?}",
                    impl_did);
 
-            if impl_did.krate != LOCAL_CRATE {
+            let impl_node_id = if let Some(n) = tcx.map.as_local_node_id(impl_did) {
+                n
+            } else {
                 debug!("check_implementations_of_coerce_unsized(): impl not \
                         in this crate");
                 return;
-            }
+            };
 
             let source = tcx.lookup_item_type(impl_did).ty;
             let trait_ref = self.crate_context.tcx.impl_trait_ref(impl_did).unwrap();
@@ -429,8 +365,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (bound)",
                    source, target);
 
-            let span = tcx.map.span(impl_did.node);
-            let param_env = ParameterEnvironment::for_item(tcx, impl_did.node);
+            let span = tcx.map.span(impl_node_id);
+            let param_env = ParameterEnvironment::for_item(tcx, impl_node_id);
             let source = source.subst(tcx, &param_env.free_substs);
             let target = target.subst(tcx, &param_env.free_substs);
             assert!(!source.has_escaping_regions());
@@ -477,9 +413,16 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                     let fields = &def_a.struct_variant().fields;
                     let diff_fields = fields.iter().enumerate().filter_map(|(i, f)| {
                         let (a, b) = (f.ty(tcx, substs_a), f.ty(tcx, substs_b));
-                        if infcx.sub_types(false, origin, b, a).is_ok() {
+
+                        if f.unsubst_ty().is_phantom_data() {
+                            // Ignore PhantomData fields
+                            None
+                        } else if infcx.sub_types(false, origin, b, a).is_ok() {
+                            // Ignore fields that aren't significantly changed
                             None
                         } else {
+                            // Collect up all fields that were significantly changed
+                            // i.e. those that contain T in coerce_unsized T -> U
                             Some((i, a, b))
                         }
                     }).collect::<Vec<_>>();
@@ -523,7 +466,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             let mut fulfill_cx = infcx.fulfillment_cx.borrow_mut();
 
             // Register an obligation for `A: Trait<B>`.
-            let cause = traits::ObligationCause::misc(span, impl_did.node);
+            let cause = traits::ObligationCause::misc(span, impl_node_id);
             let predicate = traits::predicate_for_trait_def(tcx, cause, trait_def_id,
                                                             0, source, vec![target]);
             fulfill_cx.register_predicate_obligation(&infcx, predicate);
@@ -537,7 +480,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             let mut free_regions = FreeRegionMap::new();
             free_regions.relate_free_regions_from_predicates(tcx, &infcx.parameter_environment
                                                                         .caller_bounds);
-            infcx.resolve_regions_and_report_errors(&free_regions, impl_did.node);
+            infcx.resolve_regions_and_report_errors(&free_regions, impl_node_id);
 
             if let Some(kind) = kind {
                 tcx.custom_coerce_unsized_kinds.borrow_mut().insert(impl_did, kind);
@@ -568,55 +511,6 @@ fn enforce_trait_manually_implementable(tcx: &ty::ctxt, sp: Span, trait_def_id:
                "add `#![feature(unboxed_closures)]` to the crate attributes to enable");
 }
 
-fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                           impl_id: DefId,
-                                           impl_type_scheme: &ty::TypeScheme<'tcx>,
-                                           trait_ref: &ty::TraitRef<'tcx>,
-                                           new_def_id: DefId,
-                                           method: &ty::Method<'tcx>,
-                                           provided_source: Option<DefId>)
-                                           -> ty::Method<'tcx>
-{
-    let combined_substs = tcx.make_substs_for_receiver_types(trait_ref, method);
-
-    debug!("subst_receiver_types_in_method_ty: combined_substs={:?}",
-           combined_substs);
-
-    let method_predicates = method.predicates.subst(tcx, &combined_substs);
-    let mut method_generics = method.generics.subst(tcx, &combined_substs);
-
-    // replace the type parameters declared on the trait with those
-    // from the impl
-    for &space in &[subst::TypeSpace, subst::SelfSpace] {
-        method_generics.types.replace(
-            space,
-            impl_type_scheme.generics.types.get_slice(space).to_vec());
-        method_generics.regions.replace(
-            space,
-            impl_type_scheme.generics.regions.get_slice(space).to_vec());
-    }
-
-    debug!("subst_receiver_types_in_method_ty: method_generics={:?}",
-           method_generics);
-
-    let method_fty = method.fty.subst(tcx, &combined_substs);
-
-    debug!("subst_receiver_types_in_method_ty: method_ty={:?}",
-           method.fty);
-
-    ty::Method::new(
-        method.name,
-        method_generics,
-        method_predicates,
-        method_fty,
-        method.explicit_self,
-        method.vis,
-        new_def_id,
-        ImplContainer(impl_id),
-        provided_source
-    )
-}
-
 pub fn check_coherence(crate_context: &CrateCtxt) {
     CoherenceChecker {
         crate_context: crate_context,
index 022f1e3646a12f6e599ff1754e9b1985e99436e7..f796f7fe9f9bd0d191d0ac8eefd811d9c146b936 100644 (file)
 //! Orphan checker: every impl either implements a trait defined in this
 //! crate or pertains to a type defined in this crate.
 
-use middle::def_id::{DefId, LOCAL_CRATE};
+use metadata::cstore::LOCAL_CRATE;
+use middle::def_id::DefId;
 use middle::traits;
 use middle::ty;
+use syntax::ast;
 use syntax::codemap::Span;
 use rustc_front::visit;
 use rustc_front::hir;
@@ -62,7 +64,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
     /// to prevent inundating the user with a bunch of similar error
     /// reports.
     fn check_item(&self, item: &hir::Item) {
-        let def_id = DefId::local(item.id);
+        let def_id = self.tcx.map.local_def_id(item.id);
         match item.node {
             hir::ItemImpl(_, _, _, None, _, _) => {
                 // For inherent impls, self type must be a nominal type
@@ -119,84 +121,84 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
                                                   "*mut T",
                                                   item.span);
                     }
-                    ty::TyInt(hir::TyI8) => {
+                    ty::TyInt(ast::TyI8) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.i8_impl(),
                                                   "i8",
                                                   "i8",
                                                   item.span);
                     }
-                    ty::TyInt(hir::TyI16) => {
+                    ty::TyInt(ast::TyI16) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.i16_impl(),
                                                   "i16",
                                                   "i16",
                                                   item.span);
                     }
-                    ty::TyInt(hir::TyI32) => {
+                    ty::TyInt(ast::TyI32) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.i32_impl(),
                                                   "i32",
                                                   "i32",
                                                   item.span);
                     }
-                    ty::TyInt(hir::TyI64) => {
+                    ty::TyInt(ast::TyI64) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.i64_impl(),
                                                   "i64",
                                                   "i64",
                                                   item.span);
                     }
-                    ty::TyInt(hir::TyIs) => {
+                    ty::TyInt(ast::TyIs) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.isize_impl(),
                                                   "isize",
                                                   "isize",
                                                   item.span);
                     }
-                    ty::TyUint(hir::TyU8) => {
+                    ty::TyUint(ast::TyU8) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.u8_impl(),
                                                   "u8",
                                                   "u8",
                                                   item.span);
                     }
-                    ty::TyUint(hir::TyU16) => {
+                    ty::TyUint(ast::TyU16) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.u16_impl(),
                                                   "u16",
                                                   "u16",
                                                   item.span);
                     }
-                    ty::TyUint(hir::TyU32) => {
+                    ty::TyUint(ast::TyU32) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.u32_impl(),
                                                   "u32",
                                                   "u32",
                                                   item.span);
                     }
-                    ty::TyUint(hir::TyU64) => {
+                    ty::TyUint(ast::TyU64) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.u64_impl(),
                                                   "u64",
                                                   "u64",
                                                   item.span);
                     }
-                    ty::TyUint(hir::TyUs) => {
+                    ty::TyUint(ast::TyUs) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.usize_impl(),
                                                   "usize",
                                                   "usize",
                                                   item.span);
                     }
-                    ty::TyFloat(hir::TyF32) => {
+                    ty::TyFloat(ast::TyF32) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.f32_impl(),
                                                   "f32",
                                                   "f32",
                                                   item.span);
                     }
-                    ty::TyFloat(hir::TyF64) => {
+                    ty::TyFloat(ast::TyF64) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.f64_impl(),
                                                   "f64",
index 55b5f665d11f62d5f4f4a2502d411044b1e9f7ac..706f28f9fe4b03af30b7f358de1fec029007e17a 100644 (file)
@@ -11,7 +11,8 @@
 //! Overlap: No two impls for the same trait are implemented for the
 //! same type.
 
-use middle::def_id::{DefId, LOCAL_CRATE};
+use metadata::cstore::LOCAL_CRATE;
+use middle::def_id::DefId;
 use middle::traits;
 use middle::ty;
 use middle::infer::{self, new_infer_ctxt};
@@ -111,7 +112,7 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
             }
         } else if impl2_def_id.krate != LOCAL_CRATE {
             Some((impl1_def_id, impl2_def_id))
-        } else if impl1_def_id.node < impl2_def_id.node {
+        } else if impl1_def_id < impl2_def_id {
             Some((impl1_def_id, impl2_def_id))
         } else {
             Some((impl2_def_id, impl1_def_id))
@@ -164,8 +165,8 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
     }
 
     fn span_of_impl(&self, impl_did: DefId) -> Span {
-        assert_eq!(impl_did.krate, LOCAL_CRATE);
-        self.tcx.map.span(impl_did.node)
+        let node_id = self.tcx.map.as_local_node_id(impl_did).unwrap();
+        self.tcx.map.span(node_id)
     }
 }
 
@@ -177,20 +178,20 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
                 // look for another default impl; note that due to the
                 // general orphan/coherence rules, it must always be
                 // in this crate.
-                let impl_def_id = DefId::local(item.id);
+                let impl_def_id = self.tcx.map.local_def_id(item.id);
                 let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
                 let prev_default_impl = self.default_impls.insert(trait_ref.def_id, item.id);
                 match prev_default_impl {
                     Some(prev_id) => {
                         self.report_overlap_error(trait_ref.def_id,
                                                   impl_def_id,
-                                                  DefId::local(prev_id));
+                                                  self.tcx.map.local_def_id(prev_id));
                     }
                     None => { }
                 }
             }
             hir::ItemImpl(_, _, _, Some(_), ref self_ty, _) => {
-                let impl_def_id = DefId::local(item.id);
+                let impl_def_id = self.tcx.map.local_def_id(item.id);
                 let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
                 let trait_def_id = trait_ref.def_id;
                 match trait_ref.self_ty().sty {
index b739709e622c25270ec07864c023723df27cb757..f7b10b9001340097e9faa11ed7120bb709a0d492 100644 (file)
@@ -11,7 +11,6 @@
 //! Unsafety checker: every impl either implements a trait defined in this
 //! crate or pertains to a type defined in this crate.
 
-use middle::def_id::DefId;
 use middle::ty;
 use rustc_front::visit;
 use rustc_front::hir;
@@ -30,7 +29,7 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
     fn check_unsafety_coherence(&mut self, item: &'v hir::Item,
                                 unsafety: hir::Unsafety,
                                 polarity: hir::ImplPolarity) {
-        match self.tcx.impl_trait_ref(DefId::local(item.id)) {
+        match self.tcx.impl_trait_ref(self.tcx.map.local_def_id(item.id)) {
             None => {
                 // Inherent impl.
                 match unsafety {
index f7520ed54b77e3f153d8782fb9c1c29ccf29a190..2b46dbeecb841b9163c897366b0899237f02c1b3 100644 (file)
@@ -66,7 +66,7 @@ There are some shortcomings in this design:
 
 use astconv::{self, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region};
 use middle::def;
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::DefId;
 use constrained_type_params as ctp;
 use middle::lang_items::SizedTraitLangItem;
 use middle::free_region::FreeRegionMap;
@@ -93,12 +93,12 @@ use std::rc::Rc;
 
 use syntax::abi;
 use syntax::ast;
+use syntax::attr;
 use syntax::codemap::Span;
 use syntax::parse::token::special_idents;
 use syntax::ptr::P;
 use rustc_front::hir;
 use rustc_front::visit;
-use rustc_front::attr;
 use rustc_front::print::pprust;
 
 ///////////////////////////////////////////////////////////////////////////
@@ -198,7 +198,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
     }
 
     fn method_ty(&self, method_id: ast::NodeId) -> Rc<ty::Method<'tcx>> {
-        let def_id = DefId::local(method_id);
+        let def_id = self.tcx.map.local_def_id(method_id);
         match *self.tcx.impl_or_trait_items.borrow().get(&def_id).unwrap() {
             ty::MethodTraitItem(ref mty) => mty.clone(),
             _ => {
@@ -316,16 +316,16 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
     {
         let tcx = self.tcx;
 
-        if trait_id.krate != LOCAL_CRATE {
-            return tcx.lookup_trait_def(trait_id)
-        }
-
-        let item = match tcx.map.get(trait_id.node) {
-            hir_map::NodeItem(item) => item,
-            _ => tcx.sess.bug(&format!("get_trait_def({:?}): not an item", trait_id))
-        };
+        if let Some(trait_id) = tcx.map.as_local_node_id(trait_id) {
+            let item = match tcx.map.get(trait_id) {
+                hir_map::NodeItem(item) => item,
+                _ => tcx.sess.bug(&format!("get_trait_def({:?}): not an item", trait_id))
+            };
 
-        trait_def_of_item(self, &*item)
+            trait_def_of_item(self, &*item)
+        } else {
+            tcx.lookup_trait_def(trait_id)
+        }
     }
 
     /// Ensure that the (transitive) super predicates for
@@ -402,8 +402,8 @@ impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> {
                                            assoc_name: ast::Name)
                                            -> bool
     {
-        if trait_def_id.is_local() {
-            trait_defines_associated_type_named(self.ccx, trait_def_id.node, assoc_name)
+        if let Some(trait_id) = self.tcx().map.as_local_node_id(trait_def_id) {
+            trait_defines_associated_type_named(self.ccx, trait_id, assoc_name)
         } else {
             let trait_def = self.tcx().lookup_trait_def(trait_def_id);
             trait_def.associated_type_names.contains(&assoc_name)
@@ -507,7 +507,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
 /// Find bounds from hir::Generics. This requires scanning through the
 /// AST. We do this to avoid having to convert *all* the bounds, which
 /// would create artificial cycles. Instead we can only convert the
-/// bounds for those a type parameter `X` if `X::Foo` is used.
+/// bounds for a type parameter `X` if `X::Foo` is used.
 impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics {
     fn get_type_parameter_bounds(&self,
                                  astconv: &AstConv<'tcx>,
@@ -558,10 +558,10 @@ fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
         let path_res = *tcx.def_map.borrow().get(&ast_ty.id).unwrap();
         match path_res.base_def {
             def::DefSelfTy(Some(def_id), None) => {
-                path_res.depth == 0 && def_id.node == param_id
+                path_res.depth == 0 && def_id == tcx.map.local_def_id(param_id)
             }
             def::DefTyParam(_, _, def_id, _) => {
-                path_res.depth == 0 && def_id == DefId::local(param_id)
+                path_res.depth == 0 && def_id == tcx.map.local_def_id(param_id)
             }
             _ => {
                 false
@@ -577,7 +577,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             container: ImplOrTraitItemContainer,
                             sig: &hir::MethodSig,
                             id: ast::NodeId,
-                            ident: ast::Ident,
+                            name: ast::Name,
                             vis: hir::Visibility,
                             untransformed_rcvr_ty: Ty<'tcx>,
                             rcvr_ty_generics: &ty::Generics<'tcx>,
@@ -591,21 +591,20 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         astconv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
                               sig, untransformed_rcvr_ty);
 
-    let def_id = DefId::local(id);
-    let ty_method = ty::Method::new(ident.name,
+    let def_id = ccx.tcx.map.local_def_id(id);
+    let ty_method = ty::Method::new(name,
                                     ty_generics,
                                     ty_generic_predicates,
                                     fty,
                                     explicit_self_category,
                                     vis,
                                     def_id,
-                                    container,
-                                    None);
+                                    container);
 
     let fty = ccx.tcx.mk_fn(Some(def_id),
                             ccx.tcx.mk_bare_fn(ty_method.fty.clone()));
     debug!("method {} (id {}) has type {:?}",
-            ident, id, fty);
+            name, id, fty);
     ccx.tcx.register_item_type(def_id, TypeScheme {
         generics: ty_method.generics.clone(),
         ty: fty
@@ -632,57 +631,56 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     write_ty_to_tcx(ccx.tcx, v.node.id, tt);
 
     /* add the field to the tcache */
-    ccx.tcx.register_item_type(DefId::local(v.node.id),
+    ccx.tcx.register_item_type(ccx.tcx.map.local_def_id(v.node.id),
                                ty::TypeScheme {
                                    generics: struct_generics.clone(),
                                    ty: tt
                                });
-    ccx.tcx.predicates.borrow_mut().insert(DefId::local(v.node.id),
+    ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(v.node.id),
                                            struct_predicates.clone());
 }
 
 fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                       container: ImplOrTraitItemContainer,
-                                      ident: ast::Ident,
+                                      name: ast::Name,
                                       id: ast::NodeId,
                                       vis: hir::Visibility,
                                       ty: ty::Ty<'tcx>,
-                                      default: Option<&hir::Expr>)
+                                      has_value: bool)
 {
-    ccx.tcx.predicates.borrow_mut().insert(DefId::local(id),
+    ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(id),
                                            ty::GenericPredicates::empty());
 
     write_ty_to_tcx(ccx.tcx, id, ty);
-    let default_id = default.map(|expr| DefId::local(expr.id));
 
     let associated_const = Rc::new(ty::AssociatedConst {
-        name: ident.name,
+        name: name,
         vis: vis,
-        def_id: DefId::local(id),
+        def_id: ccx.tcx.map.local_def_id(id),
         container: container,
         ty: ty,
-        default: default_id,
+        has_value: has_value
     });
     ccx.tcx.impl_or_trait_items.borrow_mut()
-       .insert(DefId::local(id), ty::ConstTraitItem(associated_const));
+       .insert(ccx.tcx.map.local_def_id(id), ty::ConstTraitItem(associated_const));
 }
 
 fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                      container: ImplOrTraitItemContainer,
-                                     ident: ast::Ident,
+                                     name: ast::Name,
                                      id: ast::NodeId,
                                      vis: hir::Visibility,
                                      ty: Option<Ty<'tcx>>)
 {
     let associated_type = Rc::new(ty::AssociatedType {
-        name: ident.name,
+        name: name,
         vis: vis,
         ty: ty,
-        def_id: DefId::local(id),
+        def_id: ccx.tcx.map.local_def_id(id),
         container: container
     });
     ccx.tcx.impl_or_trait_items.borrow_mut()
-       .insert(DefId::local(id), ty::TypeTraitItem(associated_type));
+       .insert(ccx.tcx.map.local_def_id(id), ty::TypeTraitItem(associated_type));
 }
 
 fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
@@ -691,7 +689,7 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
                                  untransformed_rcvr_ty: Ty<'tcx>,
                                  rcvr_ty_generics: &ty::Generics<'tcx>,
                                  rcvr_ty_predicates: &ty::GenericPredicates<'tcx>)
-    where I: Iterator<Item=(&'i hir::MethodSig, ast::NodeId, ast::Ident, hir::Visibility, Span)>
+    where I: Iterator<Item=(&'i hir::MethodSig, ast::NodeId, ast::Name, hir::Visibility, Span)>
 {
     debug!("convert_methods(untransformed_rcvr_ty={:?}, rcvr_ty_generics={:?}, \
                             rcvr_ty_predicates={:?})",
@@ -699,12 +697,12 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
            rcvr_ty_generics,
            rcvr_ty_predicates);
 
-    for (sig, id, ident, vis, _span) in methods {
+    for (sig, id, name, vis, _span) in methods {
         convert_method(ccx,
                        container,
                        sig,
                        id,
-                       ident,
+                       name,
                        vis,
                        untransformed_rcvr_ty,
                        rcvr_ty_generics,
@@ -743,7 +741,7 @@ fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
 
 fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
     let tcx = ccx.tcx;
-    debug!("convert: item {} with id {}", it.ident, it.id);
+    debug!("convert: item {} with id {}", it.name, it.id);
     match it.node {
         // These don't define types.
         hir::ItemExternCrate(_) | hir::ItemUse(_) |
@@ -753,7 +751,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
             let (scheme, predicates) = convert_typed_item(ccx, it);
             write_ty_to_tcx(tcx, it.id, scheme.ty);
             convert_enum_variant_types(ccx,
-                                       tcx.lookup_adt_def_master(DefId::local(it.id)),
+                                       tcx.lookup_adt_def_master(ccx.tcx.map.local_def_id(it.id)),
                                        scheme,
                                        predicates,
                                        &enum_definition.variants);
@@ -767,7 +765,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
 
             tcx.record_trait_has_default_impl(trait_ref.def_id);
 
-            tcx.impl_trait_refs.borrow_mut().insert(DefId::local(it.id), Some(trait_ref));
+            tcx.impl_trait_refs.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id),
+                                                    Some(trait_ref));
         }
         hir::ItemImpl(_, _,
                       ref generics,
@@ -784,21 +783,21 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
             let selfty = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, &**selfty);
             write_ty_to_tcx(tcx, it.id, selfty);
 
-            tcx.register_item_type(DefId::local(it.id),
+            tcx.register_item_type(ccx.tcx.map.local_def_id(it.id),
                                    TypeScheme { generics: ty_generics.clone(),
                                                 ty: selfty });
-            tcx.predicates.borrow_mut().insert(DefId::local(it.id),
+            tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id),
                                                ty_predicates.clone());
             if let &Some(ref ast_trait_ref) = opt_trait_ref {
                 tcx.impl_trait_refs.borrow_mut().insert(
-                    DefId::local(it.id),
+                    ccx.tcx.map.local_def_id(it.id),
                     Some(astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
                                                              &ExplicitRscope,
                                                              ast_trait_ref,
                                                              Some(selfty)))
                         );
             } else {
-                tcx.impl_trait_refs.borrow_mut().insert(DefId::local(it.id), None);
+                tcx.impl_trait_refs.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id), None);
             }
 
 
@@ -823,7 +822,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
                     hir::TypeImplItem(_) => &mut seen_type_items,
                     _                    => &mut seen_value_items,
                 };
-                if !seen_items.insert(impl_item.ident.name) {
+                if !seen_items.insert(impl_item.name) {
                     let desc = match impl_item.node {
                         hir::ConstImplItem(_, _) => "associated constant",
                         hir::TypeImplItem(_) => "associated type",
@@ -837,18 +836,18 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
                     span_err!(tcx.sess, impl_item.span, E0201, "duplicate {}", desc);
                 }
 
-                if let hir::ConstImplItem(ref ty, ref expr) = impl_item.node {
+                if let hir::ConstImplItem(ref ty, _) = impl_item.node {
                     let ty = ccx.icx(&ty_predicates)
                                 .to_ty(&ExplicitRscope, &*ty);
-                    tcx.register_item_type(DefId::local(impl_item.id),
+                    tcx.register_item_type(ccx.tcx.map.local_def_id(impl_item.id),
                                            TypeScheme {
                                                generics: ty_generics.clone(),
                                                ty: ty,
                                            });
-                    convert_associated_const(ccx, ImplContainer(DefId::local(it.id)),
-                                             impl_item.ident, impl_item.id,
+                    convert_associated_const(ccx, ImplContainer(ccx.tcx.map.local_def_id(it.id)),
+                                             impl_item.name, impl_item.id,
                                              impl_item.vis.inherit_from(parent_visibility),
-                                             ty, Some(&*expr));
+                                             ty, true /* has_value */);
                 }
             }
 
@@ -862,8 +861,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
 
                     let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty);
 
-                    convert_associated_type(ccx, ImplContainer(DefId::local(it.id)),
-                                            impl_item.ident, impl_item.id, impl_item.vis,
+                    convert_associated_type(ccx, ImplContainer(ccx.tcx.map.local_def_id(it.id)),
+                                            impl_item.name, impl_item.id, impl_item.vis,
                                             Some(typ));
                 }
             }
@@ -875,13 +874,13 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
                     // { fn foo(); }` is public, but private in `impl { fn
                     // foo(); }`).
                     let method_vis = ii.vis.inherit_from(parent_visibility);
-                    Some((sig, ii.id, ii.ident, method_vis, ii.span))
+                    Some((sig, ii.id, ii.name, method_vis, ii.span))
                 } else {
                     None
                 }
             });
             convert_methods(ccx,
-                            ImplContainer(DefId::local(it.id)),
+                            ImplContainer(ccx.tcx.map.local_def_id(it.id)),
                             methods,
                             selfty,
                             &ty_generics,
@@ -901,15 +900,15 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
 
             enforce_impl_params_are_constrained(tcx,
                                                 generics,
-                                                DefId::local(it.id),
+                                                ccx.tcx.map.local_def_id(it.id),
                                                 impl_items);
         },
         hir::ItemTrait(_, _, _, ref trait_items) => {
             let trait_def = trait_def_of_item(ccx, it);
             let _: Result<(), ErrorReported> = // any error is already reported, can ignore
-                ccx.ensure_super_predicates(it.span, DefId::local(it.id));
+                ccx.ensure_super_predicates(it.span, ccx.tcx.map.local_def_id(it.id));
             convert_trait_predicates(ccx, it);
-            let trait_predicates = tcx.lookup_predicates(DefId::local(it.id));
+            let trait_predicates = tcx.lookup_predicates(ccx.tcx.map.local_def_id(it.id));
 
             debug!("convert: trait_bounds={:?}", trait_predicates);
 
@@ -919,14 +918,18 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
                     hir::ConstTraitItem(ref ty, ref default) => {
                         let ty = ccx.icx(&trait_predicates)
                                     .to_ty(&ExplicitRscope, ty);
-                        tcx.register_item_type(DefId::local(trait_item.id),
+                        tcx.register_item_type(ccx.tcx.map.local_def_id(trait_item.id),
                                                TypeScheme {
                                                    generics: trait_def.generics.clone(),
                                                    ty: ty,
                                                });
-                        convert_associated_const(ccx, TraitContainer(DefId::local(it.id)),
-                                                 trait_item.ident, trait_item.id,
-                                                 hir::Public, ty, default.as_ref().map(|d| &**d));
+                        convert_associated_const(ccx,
+                                                 TraitContainer(ccx.tcx.map.local_def_id(it.id)),
+                                                 trait_item.name,
+                                                 trait_item.id,
+                                                 hir::Public,
+                                                 ty,
+                                                 default.is_some())
                     }
                     _ => {}
                 }
@@ -940,8 +943,11 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
                             |ty| ccx.icx(&trait_predicates).to_ty(&ExplicitRscope, &ty)
                         });
 
-                        convert_associated_type(ccx, TraitContainer(DefId::local(it.id)),
-                                                trait_item.ident, trait_item.id, hir::Public,
+                        convert_associated_type(ccx,
+                                                TraitContainer(ccx.tcx.map.local_def_id(it.id)),
+                                                trait_item.name,
+                                                trait_item.id,
+                                                hir::Public,
                                                 typ);
                     }
                     _ => {}
@@ -953,12 +959,12 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
                     hir::MethodTraitItem(ref sig, _) => sig,
                     _ => return None,
                 };
-                Some((sig, ti.id, ti.ident, hir::Inherited, ti.span))
+                Some((sig, ti.id, ti.name, hir::Inherited, ti.span))
             });
 
             // Run convert_methods on the trait methods.
             convert_methods(ccx,
-                            TraitContainer(DefId::local(it.id)),
+                            TraitContainer(ccx.tcx.map.local_def_id(it.id)),
                             methods,
                             tcx.mk_self_type(),
                             &trait_def.generics,
@@ -966,7 +972,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
 
             // Add an entry mapping
             let trait_item_def_ids = Rc::new(trait_items.iter().map(|trait_item| {
-                let def_id = DefId::local(trait_item.id);
+                let def_id = ccx.tcx.map.local_def_id(trait_item.id);
                 match trait_item.node {
                     hir::ConstTraitItem(..) => {
                         ty::ConstTraitItemId(def_id)
@@ -979,7 +985,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
                     }
                 }
             }).collect());
-            tcx.trait_item_def_ids.borrow_mut().insert(DefId::local(it.id), trait_item_def_ids);
+            tcx.trait_item_def_ids.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id),
+                                                       trait_item_def_ids);
 
             // This must be done after `collect_trait_methods` so that
             // we have a method type stored for every method.
@@ -1000,14 +1007,15 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
             let (scheme, predicates) = convert_typed_item(ccx, it);
             write_ty_to_tcx(tcx, it.id, scheme.ty);
 
-            let variant = tcx.lookup_adt_def_master(DefId::local(it.id)).struct_variant();
+            let it_def_id = ccx.tcx.map.local_def_id(it.id);
+            let variant = tcx.lookup_adt_def_master(it_def_id).struct_variant();
 
-            for (f, ty_f) in struct_def.fields.iter().zip(variant.fields.iter()) {
+            for (f, ty_f) in struct_def.fields().iter().zip(variant.fields.iter()) {
                 convert_field(ccx, &scheme.generics, &predicates, f, ty_f)
             }
 
-            if let Some(ctor_id) = struct_def.ctor_id {
-                convert_variant_ctor(tcx, ctor_id, variant, scheme, predicates);
+            if !struct_def.is_struct() {
+                convert_variant_ctor(tcx, struct_def.id(), variant, scheme, predicates);
             }
         },
         hir::ItemTy(_, ref generics) => {
@@ -1031,21 +1039,21 @@ fn convert_variant_ctor<'a, 'tcx>(tcx: &ty::ctxt<'tcx>,
                                   scheme: ty::TypeScheme<'tcx>,
                                   predicates: ty::GenericPredicates<'tcx>) {
     let ctor_ty = match variant.kind() {
-        VariantKind::Unit | VariantKind::Dict => scheme.ty,
+        VariantKind::Unit | VariantKind::Struct => scheme.ty,
         VariantKind::Tuple => {
             let inputs: Vec<_> =
                 variant.fields
                 .iter()
                 .map(|field| field.unsubst_ty())
                 .collect();
-            tcx.mk_ctor_fn(DefId::local(ctor_id),
+            tcx.mk_ctor_fn(tcx.map.local_def_id(ctor_id),
                            &inputs[..],
                            scheme.ty)
         }
     };
     write_ty_to_tcx(tcx, ctor_id, ctor_ty);
-    tcx.predicates.borrow_mut().insert(DefId::local(ctor_id), predicates);
-    tcx.register_item_type(DefId::local(ctor_id),
+    tcx.predicates.borrow_mut().insert(tcx.map.local_def_id(ctor_id), predicates);
+    tcx.register_item_type(tcx.map.local_def_id(ctor_id),
                            TypeScheme {
                                generics: scheme.generics,
                                ty: ctor_ty
@@ -1057,32 +1065,17 @@ fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                         scheme: ty::TypeScheme<'tcx>,
                                         predicates: ty::GenericPredicates<'tcx>,
                                         variants: &[P<hir::Variant>]) {
-    let tcx = ccx.tcx;
-    let icx = ccx.icx(&predicates);
-
     // fill the field types
     for (variant, ty_variant) in variants.iter().zip(def.variants.iter()) {
-        match variant.node.kind {
-            hir::TupleVariantKind(ref args) => {
-                let rs = ExplicitRscope;
-                let input_tys: Vec<_> = args.iter().map(|va| icx.to_ty(&rs, &*va.ty)).collect();
-                for (field, &ty) in ty_variant.fields.iter().zip(input_tys.iter()) {
-                    field.fulfill_ty(ty);
-                }
-            }
-
-            hir::StructVariantKind(ref struct_def) => {
-                for (f, ty_f) in struct_def.fields.iter().zip(ty_variant.fields.iter()) {
-                    convert_field(ccx, &scheme.generics, &predicates, f, ty_f)
-                }
-            }
-        };
+        for (f, ty_f) in variant.node.data.fields().iter().zip(ty_variant.fields.iter()) {
+            convert_field(ccx, &scheme.generics, &predicates, f, ty_f)
+        }
 
         // Convert the ctor, if any. This also registers the variant as
         // an item.
         convert_variant_ctor(
-            tcx,
-            variant.node.id,
+            ccx.tcx,
+            variant.node.data.id(),
             ty_variant,
             scheme.clone(),
             predicates.clone()
@@ -1094,23 +1087,23 @@ fn convert_struct_variant<'tcx>(tcx: &ty::ctxt<'tcx>,
                                 did: DefId,
                                 name: ast::Name,
                                 disr_val: ty::Disr,
-                                def: &hir::StructDef) -> ty::VariantDefData<'tcx, 'tcx> {
+                                def: &hir::VariantData) -> ty::VariantDefData<'tcx, 'tcx> {
     let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap();
-    let fields = def.fields.iter().map(|f| {
-        let fid = DefId::local(f.node.id);
+    let fields = def.fields().iter().map(|f| {
+        let fid = tcx.map.local_def_id(f.node.id);
         match f.node.kind {
-            hir::NamedField(ident, vis) => {
-                let dup_span = seen_fields.get(&ident.name).cloned();
+            hir::NamedField(name, vis) => {
+                let dup_span = seen_fields.get(&name).cloned();
                 if let Some(prev_span) = dup_span {
                     span_err!(tcx.sess, f.span, E0124,
                               "field `{}` is already declared",
-                              ident.name);
+                              name);
                     span_note!(tcx.sess, prev_span, "previously declared here");
                 } else {
-                    seen_fields.insert(ident.name, f.span);
+                    seen_fields.insert(name, f.span);
                 }
 
-                ty::FieldDefData::new(fid, ident.name, vis)
+                ty::FieldDefData::new(fid, name, vis)
             },
             hir::UnnamedField(vis) => {
                 ty::FieldDefData::new(fid, special_idents::unnamed_field.name, vis)
@@ -1127,15 +1120,20 @@ fn convert_struct_variant<'tcx>(tcx: &ty::ctxt<'tcx>,
 
 fn convert_struct_def<'tcx>(tcx: &ty::ctxt<'tcx>,
                             it: &hir::Item,
-                            def: &hir::StructDef)
+                            def: &hir::VariantData)
                             -> ty::AdtDefMaster<'tcx>
 {
 
-    let did = DefId::local(it.id);
+    let did = tcx.map.local_def_id(it.id);
+    let ctor_id = if !def.is_struct() {
+        tcx.map.local_def_id(def.id())
+    } else {
+        did
+    };
     tcx.intern_adt_def(
         did,
         ty::AdtKind::Struct,
-        vec![convert_struct_variant(tcx, did, it.ident.name, 0, def)]
+        vec![convert_struct_variant(tcx, ctor_id, it.name, 0, def)]
     )
 }
 
@@ -1150,7 +1148,7 @@ fn convert_enum_def<'tcx>(tcx: &ty::ctxt<'tcx>,
         debug!("disr expr, checking {}", pprust::expr_to_string(e));
 
         let hint = UncheckedExprHint(repr_ty);
-        match const_eval::eval_const_expr_partial(tcx, e, hint) {
+        match const_eval::eval_const_expr_partial(tcx, e, hint, None) {
             Ok(ConstVal::Int(val)) => Some(val as ty::Disr),
             Ok(ConstVal::Uint(val)) => Some(val as ty::Disr),
             Ok(_) => {
@@ -1165,9 +1163,12 @@ fn convert_enum_def<'tcx>(tcx: &ty::ctxt<'tcx>,
                 None
             },
             Err(err) => {
-              span_err!(tcx.sess, err.span, E0080,
-                        "constant evaluation error: {}",
-                        err.description());
+                span_err!(tcx.sess, err.span, E0080,
+                          "constant evaluation error: {}",
+                          err.description());
+                if !e.span.contains(err.span) {
+                    tcx.sess.span_note(e.span, "for enum discriminant here");
+                }
                 None
             }
         }
@@ -1195,7 +1196,7 @@ fn convert_enum_def<'tcx>(tcx: &ty::ctxt<'tcx>,
         if let Some(prev_disr_val) = prev_disr_val {
             let result = repr_type.disr_incr(prev_disr_val);
             if let None = result {
-                report_discrim_overflow(tcx, v.span, &v.node.name.name.as_str(),
+                report_discrim_overflow(tcx, v.span, &v.node.name.as_str(),
                                              repr_type, prev_disr_val);
             }
             result
@@ -1208,29 +1209,11 @@ fn convert_enum_def<'tcx>(tcx: &ty::ctxt<'tcx>,
                                   disr: ty::Disr)
                                   -> ty::VariantDefData<'tcx, 'tcx>
     {
-        let did = DefId::local(v.node.id);
-        let name = v.node.name.name;
-        match v.node.kind {
-            hir::TupleVariantKind(ref va) => {
-                ty::VariantDefData {
-                    did: did,
-                    name: name,
-                    disr_val: disr,
-                    fields: va.iter().map(|&hir::VariantArg { id, .. }| {
-                        ty::FieldDefData::new(
-                            DefId::local(id),
-                            special_idents::unnamed_field.name,
-                            hir::Visibility::Public
-                        )
-                    }).collect()
-                }
-            }
-            hir::StructVariantKind(ref def) => {
-                convert_struct_variant(tcx, did, name, disr, &def)
-            }
-        }
+        let did = tcx.map.local_def_id(v.node.data.id());
+        let name = v.node.name;
+        convert_struct_variant(tcx, did, name, disr, &v.node.data)
     }
-    let did = DefId::local(it.id);
+    let did = tcx.map.local_def_id(it.id);
     let repr_hints = tcx.lookup_repr_hints(did);
     let (repr_type, repr_type_ty) = tcx.enum_repr_type(repr_hints.get(0));
     let mut prev_disr = None;
@@ -1244,7 +1227,7 @@ fn convert_enum_def<'tcx>(tcx: &ty::ctxt<'tcx>,
         prev_disr = Some(disr);
         v
     }).collect();
-    tcx.intern_adt_def(DefId::local(it.id), ty::AdtKind::Enum, variants)
+    tcx.intern_adt_def(tcx.map.local_def_id(it.id), ty::AdtKind::Enum, variants)
 }
 
 /// Ensures that the super-predicates of the trait with def-id
@@ -1262,19 +1245,19 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt,
 
     debug!("ensure_super_predicates_step(trait_def_id={:?})", trait_def_id);
 
-    if trait_def_id.krate != LOCAL_CRATE {
+    let trait_node_id = if let Some(n) = tcx.map.as_local_node_id(trait_def_id) {
+        n
+    } else {
         // If this trait comes from an external crate, then all of the
         // supertraits it may depend on also must come from external
         // crates, and hence all of them already have their
         // super-predicates "converted" (and available from crate
         // meta-data), so there is no need to transitively test them.
         return Vec::new();
-    }
+    };
 
     let superpredicates = tcx.super_predicates.borrow().get(&trait_def_id).cloned();
     let superpredicates = superpredicates.unwrap_or_else(|| {
-        let trait_node_id = trait_def_id.node;
-
         let item = match ccx.tcx.map.get(trait_node_id) {
             hir_map::NodeItem(item) => item,
             _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id))
@@ -1317,7 +1300,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt,
             predicates: VecPerParamSpace::new(superbounds, vec![], vec![])
         };
         debug!("superpredicates for trait {:?} = {:?}",
-               DefId::local(item.id),
+               tcx.map.local_def_id(item.id),
                superpredicates);
 
         tcx.super_predicates.borrow_mut().insert(trait_def_id, superpredicates.clone());
@@ -1340,7 +1323,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                it: &hir::Item)
                                -> &'tcx ty::TraitDef<'tcx>
 {
-    let def_id = DefId::local(it.id);
+    let def_id = ccx.tcx.map.local_def_id(it.id);
     let tcx = ccx.tcx;
 
     if let Some(def) = tcx.trait_defs.borrow().get(&def_id) {
@@ -1369,7 +1352,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     let associated_type_names: Vec<_> = items.iter().filter_map(|trait_item| {
         match trait_item.node {
-            hir::TypeTraitItem(..) => Some(trait_item.ident.name),
+            hir::TypeTraitItem(..) => Some(trait_item.name),
             _ => None,
         }
     }).collect();
@@ -1404,7 +1387,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                     .iter()
                     .enumerate()
                     .map(|(i, def)| ty::ReEarlyBound(ty::EarlyBoundRegion {
-                        param_id: def.lifetime.id,
+                        def_id: tcx.map.local_def_id(def.lifetime.id),
                         space: TypeSpace,
                         index: i as u32,
                         name: def.lifetime.name
@@ -1417,7 +1400,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                     .iter()
                     .enumerate()
                     .map(|(i, def)| tcx.mk_param(TypeSpace,
-                                                 i as u32, def.ident.name))
+                                                 i as u32, def.name))
                     .collect();
 
         // ...and also create the `Self` parameter.
@@ -1444,7 +1427,7 @@ fn trait_defines_associated_type_named(ccx: &CrateCtxt,
 
     trait_items.iter().any(|trait_item| {
         match trait_item.node {
-            hir::TypeTraitItem(..) => trait_item.ident.name == assoc_name,
+            hir::TypeTraitItem(..) => trait_item.name == assoc_name,
             _ => false,
         }
     })
@@ -1454,7 +1437,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item)
     let tcx = ccx.tcx;
     let trait_def = trait_def_of_item(ccx, it);
 
-    let def_id = DefId::local(it.id);
+    let def_id = ccx.tcx.map.local_def_id(it.id);
 
     let (generics, items) = match it.node {
         hir::ItemTrait(_, ref generics, _, ref items) => (generics, items),
@@ -1511,7 +1494,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item)
             };
 
             let assoc_ty = ccx.tcx.mk_projection(self_trait_ref,
-                                                 trait_item.ident.name);
+                                                 trait_item.name);
 
             let bounds = compute_bounds(&ccx.icx(&(ast_generics, trait_predicates)),
                                         assoc_ty,
@@ -1528,23 +1511,23 @@ fn type_scheme_of_def_id<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                   def_id: DefId)
                                   -> ty::TypeScheme<'tcx>
 {
-    if def_id.krate != LOCAL_CRATE {
-        return ccx.tcx.lookup_item_type(def_id);
-    }
-
-    match ccx.tcx.map.find(def_id.node) {
-        Some(hir_map::NodeItem(item)) => {
-            type_scheme_of_item(ccx, &*item)
-        }
-        Some(hir_map::NodeForeignItem(foreign_item)) => {
-            let abi = ccx.tcx.map.get_foreign_abi(def_id.node);
-            type_scheme_of_foreign_item(ccx, &*foreign_item, abi)
-        }
-        x => {
-            ccx.tcx.sess.bug(&format!("unexpected sort of node \
-                                            in get_item_type_scheme(): {:?}",
-                                       x));
+    if let Some(node_id) = ccx.tcx.map.as_local_node_id(def_id) {
+        match ccx.tcx.map.find(node_id) {
+            Some(hir_map::NodeItem(item)) => {
+                type_scheme_of_item(ccx, &*item)
+            }
+            Some(hir_map::NodeForeignItem(foreign_item)) => {
+                let abi = ccx.tcx.map.get_foreign_abi(node_id);
+                type_scheme_of_foreign_item(ccx, &*foreign_item, abi)
+            }
+            x => {
+                ccx.tcx.sess.bug(&format!("unexpected sort of node \
+                                           in get_item_type_scheme(): {:?}",
+                                          x));
+            }
         }
+    } else {
+        ccx.tcx.lookup_item_type(def_id)
     }
 }
 
@@ -1553,7 +1536,7 @@ fn type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                 -> ty::TypeScheme<'tcx>
 {
     memoized(&ccx.tcx.tcache,
-             DefId::local(it.id),
+             ccx.tcx.map.local_def_id(it.id),
              |_| compute_type_scheme_of_item(ccx, it))
 }
 
@@ -1570,7 +1553,7 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
         hir::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
             let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
             let tofd = astconv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &**decl);
-            let ty = tcx.mk_fn(Some(DefId::local(it.id)), tcx.mk_bare_fn(tofd));
+            let ty = tcx.mk_fn(Some(ccx.tcx.map.local_def_id(it.id)), tcx.mk_bare_fn(tofd));
             ty::TypeScheme { ty: ty, generics: ty_generics }
         }
         hir::ItemTy(ref t, ref generics) => {
@@ -1645,12 +1628,12 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         }
     };
 
-    let prev_predicates = tcx.predicates.borrow_mut().insert(DefId::local(it.id),
+    let prev_predicates = tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id),
                                                              predicates.clone());
     assert!(prev_predicates.is_none());
 
     // Debugging aid.
-    if tcx.has_attr(DefId::local(it.id), "rustc_object_lifetime_default") {
+    if tcx.has_attr(ccx.tcx.map.local_def_id(it.id), "rustc_object_lifetime_default") {
         let object_lifetime_default_reprs: String =
             scheme.generics.types.iter()
                                  .map(|t| match t.object_lifetime_default {
@@ -1673,7 +1656,7 @@ fn type_scheme_of_foreign_item<'a, 'tcx>(
     -> ty::TypeScheme<'tcx>
 {
     memoized(&ccx.tcx.tcache,
-             DefId::local(it.id),
+             ccx.tcx.map.local_def_id(it.id),
              |_| compute_type_scheme_of_foreign_item(ccx, it, abi))
 }
 
@@ -1718,7 +1701,8 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         }
     };
 
-    let prev_predicates = tcx.predicates.borrow_mut().insert(DefId::local(it.id), predicates);
+    let prev_predicates = tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(it.id),
+                                                             predicates);
     assert!(prev_predicates.is_none());
 }
 
@@ -1742,7 +1726,7 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                    -> ty::Generics<'tcx>
 {
     debug!("ty_generics_for_trait(trait_id={:?}, substs={:?})",
-           DefId::local(trait_id), substs);
+           ccx.tcx.map.local_def_id(trait_id), substs);
 
     let mut generics = ty_generics_for_type_or_impl(ccx, ast_generics);
 
@@ -1758,8 +1742,8 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         space: SelfSpace,
         index: 0,
         name: special_idents::type_self.name,
-        def_id: DefId::local(param_id),
-        default_def_id: DefId::local(parent),
+        def_id: ccx.tcx.map.local_def_id(param_id),
+        default_def_id: ccx.tcx.map.local_def_id(parent),
         default: None,
         object_lifetime_default: ty::ObjectLifetimeDefault::BaseDefault,
     };
@@ -1862,7 +1846,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     // type parameter (e.g., `<T:Foo>`).
     for (index, param) in ast_generics.ty_params.iter().enumerate() {
         let index = index as u32;
-        let param_ty = ty::ParamTy::new(space, index, param.ident.name).to_ty(ccx.tcx);
+        let param_ty = ty::ParamTy::new(space, index, param.name).to_ty(ccx.tcx);
         let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)),
                                     param_ty,
                                     &param.bounds,
@@ -1878,9 +1862,10 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics);
     for (index, param) in early_lifetimes.iter().enumerate() {
         let index = index as u32;
+        let def_id = tcx.map.local_def_id(param.lifetime.id);
         let region =
             ty::ReEarlyBound(ty::EarlyBoundRegion {
-                param_id: param.lifetime.id,
+                def_id: def_id,
                 space: space,
                 index: index,
                 name: param.lifetime.name
@@ -1966,7 +1951,7 @@ fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
         let def = ty::RegionParameterDef { name: l.lifetime.name,
                                            space: space,
                                            index: i as u32,
-                                           def_id: DefId::local(l.lifetime.id),
+                                           def_id: ccx.tcx.map.local_def_id(l.lifetime.id),
                                            bounds: bounds };
         result.regions.push(space, def);
     }
@@ -2033,9 +2018,9 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     let def = ty::TypeParameterDef {
         space: space,
         index: index,
-        name: param.ident.name,
-        def_id: DefId::local(param.id),
-        default_def_id: DefId::local(parent),
+        name: param.name,
+        def_id: ccx.tcx.map.local_def_id(param.id),
+        default_def_id: ccx.tcx.map.local_def_id(parent),
         default: default,
         object_lifetime_default: object_lifetime_default,
     };
@@ -2378,9 +2363,10 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
         tcx.fold_regions(value, &mut false, |region, _| {
             match region {
                 ty::ReEarlyBound(data) => {
-                    let def_id = DefId::local(data.param_id);
-                    ty::ReFree(ty::FreeRegion { scope: scope,
-                                                bound_region: ty::BrNamed(def_id, data.name) })
+                    ty::ReFree(ty::FreeRegion {
+                        scope: scope,
+                        bound_region: ty::BrNamed(data.def_id, data.name)
+                    })
                 }
                 _ => region
             }
@@ -2415,7 +2401,7 @@ fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
     for (index, ty_param) in ast_generics.ty_params.iter().enumerate() {
         let param_ty = ty::ParamTy { space: TypeSpace,
                                      idx: index as u32,
-                                     name: ty_param.ident.name };
+                                     name: ty_param.name };
         if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) {
             report_unused_parameter(tcx, ty_param.span, "type", &param_ty.to_string());
         }
@@ -2425,7 +2411,7 @@ fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
 
     let lifetimes_in_associated_types: HashSet<_> =
         impl_items.iter()
-                  .map(|item| tcx.impl_or_trait_item(DefId::local(item.id)))
+                  .map(|item| tcx.impl_or_trait_item(tcx.map.local_def_id(item.id)))
                   .filter_map(|item| match item {
                       ty::TypeTraitItem(ref assoc_ty) => assoc_ty.ty,
                       ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => None
@@ -2438,7 +2424,8 @@ fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
                   .collect();
 
     for (index, lifetime_def) in ast_generics.lifetimes.iter().enumerate() {
-        let region = ty::EarlyBoundRegion { param_id: lifetime_def.lifetime.id,
+        let def_id = tcx.map.local_def_id(lifetime_def.lifetime.id);
+        let region = ty::EarlyBoundRegion { def_id: def_id,
                                             space: TypeSpace,
                                             index: index as u32,
                                             name: lifetime_def.lifetime.name };
index 78eaedfbd1b728817700d7f2ca43001338797ebb..4f39ed43b4481e20701ac1c2b15a697567813d80 100644 (file)
@@ -109,7 +109,7 @@ fn main(){
 "##,
 
 E0026: r##"
-This error indicates that a struct pattern attempted to extract a non-existant
+This error indicates that a struct pattern attempted to extract a non-existent
 field from a struct. Struct fields are identified by the name used before the
 colon `:` so struct patterns should resemble the declaration of the struct type
 being matched.
@@ -1308,8 +1308,8 @@ extern "rust-intrinsic" {
 "##,
 
 E0101: r##"
-You hit this error because the compiler the compiler lacks information
-to determine a type for this expression. Erroneous code example:
+You hit this error because the compiler lacks the information to
+determine a type for this expression. Erroneous code example:
 
 ```
 fn main() {
@@ -1390,8 +1390,7 @@ enum Bar { A(u8), B(&bool), }        // error
 enum Bar<'a> { A(u8), B(&'a bool), } // correct
 
 type MyStr = &str;        // error
-type MyStr<'a> = &'a str; //correct
-
+type MyStr<'a> = &'a str; // correct
 ```
 
 Lifetime elision is a special, limited kind of inference for lifetimes in
@@ -1779,6 +1778,58 @@ fn(isize, *const *const u8) -> isize;
 ```
 "##,
 
+E0163: r##"
+This error means that an attempt was made to match an enum variant as a
+struct type when the variant isn't a struct type:
+
+```
+enum Foo { B(u32) }
+
+fn bar(foo: Foo) -> u32 {
+    match foo {
+        Foo::B{i} => i // error 0163
+    }
+}
+```
+
+Try using `()` instead:
+
+```
+fn bar(foo: Foo) -> u32 {
+    match foo {
+        Foo::B(i) => i
+    }
+}
+```
+"##,
+
+E0164: r##"
+
+This error means that an attempt was made to match a struct type enum
+variant as a non-struct type:
+
+```
+enum Foo { B{ i: u32 } }
+
+fn bar(foo: Foo) -> u32 {
+    match foo {
+        Foo::B(i) => i // error 0164
+    }
+}
+```
+
+Try using `{}` instead:
+
+```
+fn bar(foo: Foo) -> u32 {
+    match foo {
+        Foo::B{i} => i
+    }
+}
+```
+"##,
+
+
 E0166: r##"
 This error means that the compiler found a return expression in a function
 marked as diverging. A function diverges if it has `!` in the place of the
@@ -1958,8 +2009,8 @@ wrapped type `T` implements `Clone`. The `where` clause is important because
 some types will not implement `Clone`, and thus will not get this method.
 
 In our erroneous example, however, we're referencing a single concrete type.
-Since we know for certain that Wrapper<u32> implements Clone, there's no reason
-to also specify it in a `where` clause.
+Since we know for certain that `Wrapper<u32>` implements `Clone`, there's no
+reason to also specify it in a `where` clause.
 "##,
 
 E0194: r##"
@@ -2297,8 +2348,8 @@ For information on the design of the orphan rules, see [RFC 1023].
 "##,
 
 E0211: r##"
-You used an intrinsic function which doesn't correspond to its
-definition. Erroneous code example:
+You used a function or type which doesn't fit the requirements for where it was
+used. Erroneous code examples:
 
 ```
 #![feature(intrinsics)]
@@ -2306,15 +2357,71 @@ definition. Erroneous code example:
 extern "rust-intrinsic" {
     fn size_of<T>(); // error: intrinsic has wrong type
 }
+
+// or:
+
+fn main() -> i32 { 0 }
+// error: main function expects type: `fn() {main}`: expected (), found i32
+
+// or:
+
+let x = 1u8;
+match x {
+    0u8...3i8 => (),
+    // error: mismatched types in range: expected u8, found i8
+    _ => ()
+}
+
+// or:
+
+use std::rc::Rc;
+struct Foo;
+
+impl Foo {
+    fn x(self: Rc<Foo>) {}
+    // error: mismatched self type: expected `Foo`: expected struct
+    //        `Foo`, found struct `alloc::rc::Rc`
+}
 ```
 
-Please check the function definition. Example:
+For the first code example, please check the function definition. Example:
 
 ```
 #![feature(intrinsics)]
 
 extern "rust-intrinsic" {
-    fn size_of<T>() -> usize;
+    fn size_of<T>() -> usize; // ok!
+}
+```
+
+The second case example is a bit particular : the main function must always
+have this definition:
+
+```
+fn main();
+```
+
+They never take parameters and never return types.
+
+For the third example, when you match, all patterns must have the same type
+as the type you're matching on. Example:
+
+```
+let x = 1u8;
+match x {
+    0u8...3u8 => (), // ok!
+    _ => ()
+}
+```
+
+And finally, for the last example, only `Box<Self>`, `&Self`, `Self`,
+or `&mut Self` work as explicit self parameters. Example:
+
+```
+struct Foo;
+
+impl Foo {
+    fn x(self: Box<Foo>) {} // ok!
 }
 ```
 "##,
@@ -2529,7 +2636,7 @@ In this example, we're attempting to take a type of `Foo::Bar` in the
 do_something function. This is not legal: `Foo::Bar` is a value of type `Foo`,
 not a distinct static type. Likewise, it's not legal to attempt to
 `impl Foo::Bar`: instead, you must `impl Foo` and then pattern match to specify
-behaviour for specific enum variants.
+behavior for specific enum variants.
 "##,
 
 E0249: r##"
@@ -2862,14 +2969,27 @@ impl <T: Foo> Drop for MyStructWrapper<T> {
 
 E0368: r##"
 This error indicates that a binary assignment operator like `+=` or `^=` was
-applied to the wrong types. For example:
+applied to a type that doesn't support it. For example:
+
+```
+let mut x = 12f32; // error: binary operation `<<` cannot be applied to
+               //        type `f32`
 
+x <<= 2;
 ```
-let mut x: u16 = 5;
-x ^= true; // error, `^=` cannot be applied to types `u16` and `bool`
-x += ();   // error, `+=` cannot be applied to types `u16` and `()`
+
+To fix this error, please check that this type implements this binary
+operation. Example:
+
+```
+let x = 12u32; // the `u32` type does implement the `ShlAssign` trait
+
+x <<= 2; // ok!
 ```
 
+It is also possible to overload most operators for your own type by
+implementing the `[OP]Assign` traits from `std::ops`.
+
 Another problem you might be facing is this: suppose you've overloaded the `+`
 operator for some type `Foo` by implementing the `std::ops::Add` trait for
 `Foo`, but you find that using `+=` does not work, as in this example:
@@ -2889,15 +3009,12 @@ impl Add for Foo {
 
 fn main() {
     let mut x: Foo = Foo(5);
-    x += Foo(7); // error, `+= cannot be applied to types `Foo` and `Foo`
+    x += Foo(7); // error, `+= cannot be applied to the type `Foo`
 }
 ```
 
-This is because the binary assignment operators currently do not work off of
-traits, so it is not possible to overload them. See [RFC 953] for a proposal
-to change this.
-
-[RFC 953]: https://github.com/rust-lang/rfcs/pull/953
+This is because `AddAssign` is not automatically implemented, so you need to
+manually implement it for your type.
 "##,
 
 E0369: r##"
@@ -3269,6 +3386,25 @@ extern "platform-intrinsic" {
 ```
 "##,
 
+E0516: r##"
+The `typeof` keyword is currently reserved but unimplemented.
+Erroneous code example:
+
+```
+fn main() {
+    let x: typeof(92) = 92;
+}
+```
+
+Try using type inference instead. Example:
+
+```
+fn main() {
+    let x = 92;
+}
+```
+"##,
+
 }
 
 register_diagnostics! {
@@ -3283,8 +3419,6 @@ register_diagnostics! {
 //  E0129,
 //  E0141,
 //  E0159, // use of trait `{}` as struct constructor
-    E0163,
-    E0164,
     E0167,
 //  E0168,
 //  E0173, // manual implementations of unboxed closure traits are experimental
@@ -3292,7 +3426,7 @@ register_diagnostics! {
     E0182,
     E0183,
 //  E0187, // can't infer the kind of the closure
-//  E0188, // can not cast a immutable reference to a mutable pointer
+//  E0188, // can not cast an immutable reference to a mutable pointer
 //  E0189, // deprecated: can only cast a boxed pointer to a boxed object
 //  E0190, // deprecated: can only cast a &-pointer to an &-object
     E0196, // cannot determine a type for this closure
@@ -3344,5 +3478,6 @@ register_diagnostics! {
            // type because its default value `{}` references the type `Self`"
     E0399, // trait items need to be implemented because the associated
            // type `{}` was overridden
-    E0436,  // functional record update requires a struct
+    E0436, // functional record update requires a struct
+    E0513  // no type for local variable ..
 }
index a11cd54b6580e98726c7511c9a74aa99657dd5f3..1a52df31f39ce99f21fb1aa8db259cb69fcd1828 100644 (file)
@@ -81,10 +81,8 @@ This API is completely unstable and subject to change.
 #![feature(iter_cmp)]
 #![feature(iter_arith)]
 #![feature(quote)]
-#![feature(ref_slice)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
-#![feature(slice_splits)]
 #![feature(staged_api)]
 #![feature(vec_push_all)]
 #![feature(cell_extras)]
@@ -97,21 +95,22 @@ extern crate fmt_macros;
 extern crate rustc;
 extern crate rustc_platform_intrinsics as intrinsics;
 extern crate rustc_front;
+extern crate rustc_back;
 
+pub use rustc::front;
 pub use rustc::lint;
 pub use rustc::metadata;
 pub use rustc::middle;
 pub use rustc::session;
 pub use rustc::util;
 
+use front::map as hir_map;
 use middle::def;
-use middle::def_id::DefId;
 use middle::infer;
 use middle::subst;
 use middle::ty::{self, Ty, HasTypeFlags};
 use session::config;
 use util::common::time;
-use rustc::front::map as hir_map;
 use rustc_front::hir;
 
 use syntax::codemap::Span;
@@ -239,7 +238,8 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
                 }
                 _ => ()
             }
-            let se_ty = tcx.mk_fn(Some(DefId::local(main_id)), tcx.mk_bare_fn(ty::BareFnTy {
+            let main_def_id = tcx.map.local_def_id(main_id);
+            let se_ty = tcx.mk_fn(Some(main_def_id), tcx.mk_bare_fn(ty::BareFnTy {
                 unsafety: hir::Unsafety::Normal,
                 abi: abi::Rust,
                 sig: ty::Binder(ty::FnSig {
@@ -285,7 +285,8 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
                 _ => ()
             }
 
-            let se_ty = tcx.mk_fn(Some(DefId::local(start_id)), tcx.mk_bare_fn(ty::BareFnTy {
+            let se_ty = tcx.mk_fn(Some(ccx.tcx.map.local_def_id(start_id)),
+                                  tcx.mk_bare_fn(ty::BareFnTy {
                 unsafety: hir::Unsafety::Normal,
                 abi: abi::Rust,
                 sig: ty::Binder(ty::FnSig {
index 229c52a4e5e5a415009a24438ec4822915a8db75..8152e685d8d831819bf6cff30884061247cf2ced 100644 (file)
@@ -266,7 +266,7 @@ use self::ParamKind::*;
 
 use arena;
 use arena::TypedArena;
-use middle::def_id::{DefId, LOCAL_CRATE};
+use middle::def_id::DefId;
 use middle::resolve_lifetime as rl;
 use middle::subst;
 use middle::subst::{ParamSpace, FnSpace, TypeSpace, SelfSpace, VecPerParamSpace};
@@ -403,10 +403,10 @@ fn lang_items(tcx: &ty::ctxt) -> Vec<(ast::NodeId,Vec<ty::Variance>)> {
 
         ];
 
-    all.into_iter()
+    all.into_iter() // iterating over (Option<DefId>, Variance)
        .filter(|&(ref d,_)| d.is_some())
-       .filter(|&(ref d,_)| d.as_ref().unwrap().is_local())
-       .map(|(d, v)| (d.unwrap().node, v))
+       .map(|(d, v)| (d.unwrap(), v)) // (DefId, Variance)
+       .filter_map(|(d, v)| tcx.map.as_local_node_id(d).map(|n| (n, v))) // (NodeId, Variance)
        .collect()
 }
 
@@ -451,9 +451,10 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
         // "invalid item id" from "item id with no
         // parameters".
         if self.num_inferred() == inferreds_on_entry {
+            let item_def_id = self.tcx.map.local_def_id(item_id);
             let newly_added =
                 self.tcx.item_variance_map.borrow_mut().insert(
-                    DefId::local(item_id),
+                    item_def_id,
                     self.empty_variances.clone()).is_none();
             assert!(newly_added);
         }
@@ -486,7 +487,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
                 param_id={}, \
                 inf_index={:?}, \
                 initial_variance={:?})",
-               self.tcx.item_path_str(DefId::local(item_id)),
+               self.tcx.item_path_str(self.tcx.map.local_def_id(item_id)),
                item_id, kind, space, index, param_id, inf_index,
                initial_variance);
     }
@@ -596,8 +597,8 @@ fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>,
 
 impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
     fn visit_item(&mut self, item: &hir::Item) {
-        let did = DefId::local(item.id);
         let tcx = self.terms_cx.tcx;
+        let did = tcx.map.local_def_id(item.id);
 
         debug!("visit_item item={}", tcx.map.node_to_string(item.id));
 
@@ -739,11 +740,11 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                          -> VarianceTermPtr<'a> {
         assert_eq!(param_def_id.krate, item_def_id.krate);
 
-        if param_def_id.is_local() {
+        if let Some(param_node_id) = self.tcx().map.as_local_node_id(param_def_id) {
             // Parameter on an item defined within current crate:
             // variance not yet inferred, so return a symbolic
             // variance.
-            let InferredIndex(index) = self.inferred_index(param_def_id.node);
+            let InferredIndex(index) = self.inferred_index(param_node_id);
             self.terms_cx.inferred_infos[index].term
         } else {
             // Parameter on an item defined within another crate:
@@ -922,8 +923,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
 
             ty::TyParam(ref data) => {
                 let def_id = generics.types.get(data.space, data.idx as usize).def_id;
-                assert_eq!(def_id.krate, LOCAL_CRATE);
-                match self.terms_cx.inferred_map.get(&def_id.node) {
+                let node_id = self.tcx().map.as_local_node_id(def_id).unwrap();
+                match self.terms_cx.inferred_map.get(&node_id) {
                     Some(&index) => {
                         self.add_constraint(index, variance);
                     }
@@ -1011,8 +1012,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                                    variance: VarianceTermPtr<'a>) {
         match region {
             ty::ReEarlyBound(ref data) => {
-                if self.is_to_be_inferred(data.param_id) {
-                    let index = self.inferred_index(data.param_id);
+                let node_id = self.tcx().map.as_local_node_id(data.def_id).unwrap();
+                if self.is_to_be_inferred(node_id) {
+                    let index = self.inferred_index(node_id);
                     self.add_constraint(index, variance);
                 }
             }
@@ -1163,7 +1165,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
                     item_id,
                     item_variances);
 
-            let item_def_id = DefId::local(item_id);
+            let item_def_id = tcx.map.local_def_id(item_id);
 
             // For unit testing: check for a special "rustc_variance"
             // attribute and report an error with various results if found.
index e08b3244109d579c2243f44dd79c4d38d8e145d5..2fb15ff2ac7fe419b38fe42313b194e42a72174b 100644 (file)
@@ -49,7 +49,9 @@ pub struct ToLowercase(CaseMappingIter);
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Iterator for ToLowercase {
     type Item = char;
-    fn next(&mut self) -> Option<char> { self.0.next() }
+    fn next(&mut self) -> Option<char> {
+        self.0.next()
+    }
 }
 
 /// An iterator over the uppercase mapping of a given character, returned from
@@ -61,7 +63,9 @@ pub struct ToUppercase(CaseMappingIter);
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Iterator for ToUppercase {
     type Item = char;
-    fn next(&mut self) -> Option<char> { self.0.next() }
+    fn next(&mut self) -> Option<char> {
+        self.0.next()
+    }
 }
 
 
@@ -69,7 +73,7 @@ enum CaseMappingIter {
     Three(char, char, char),
     Two(char, char),
     One(char),
-    Zero
+    Zero,
 }
 
 impl CaseMappingIter {
@@ -110,57 +114,130 @@ impl Iterator for CaseMappingIter {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[lang = "char"]
 impl char {
-    /// Checks if a `char` parses as a numeric digit in the given radix.
+    /// Checks if a `char` is a digit in the given radix.
+    ///
+    /// A 'radix' here is sometimes also called a 'base'. A radix of two
+    /// indicates a binary number, a radix of ten, decimal, and a radix of
+    /// sixteen, hexicdecimal, to give some common values. Arbitrary
+    /// radicum are supported.
     ///
     /// Compared to `is_numeric()`, this function only recognizes the characters
     /// `0-9`, `a-z` and `A-Z`.
     ///
-    /// # Return value
+    /// 'Digit' is defined to be only the following characters:
     ///
-    /// Returns `true` if `c` is a valid digit under `radix`, and `false`
-    /// otherwise.
+    /// * `0-9`
+    /// * `a-z`
+    /// * `A-Z`
+    ///
+    /// For a more comprehensive understanding of 'digit', see [`is_numeric()`][is_numeric].
+    ///
+    /// [is_numeric]: #method.is_numeric
     ///
     /// # Panics
     ///
-    /// Panics if given a radix > 36.
+    /// Panics if given a radix larger than 36.
     ///
     /// # Examples
     ///
+    /// Basic usage:
+    ///
     /// ```
-    /// let c = '1';
+    /// let d = '1';
     ///
-    /// assert!(c.is_digit(10));
+    /// assert!(d.is_digit(10));
     ///
-    /// assert!('f'.is_digit(16));
+    /// let d = 'f';
+    ///
+    /// assert!(d.is_digit(16));
+    /// assert!(!d.is_digit(10));
+    /// ```
+    ///
+    /// Passing a large radix, causing a panic:
+    ///
+    /// ```
+    /// use std::thread;
+    ///
+    /// let result = thread::spawn(|| {
+    ///     let d = '1';
+    ///
+    ///     // this panics
+    ///     d.is_digit(37);
+    /// }).join();
+    ///
+    /// assert!(result.is_err());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn is_digit(self, radix: u32) -> bool { C::is_digit(self, radix) }
+    pub fn is_digit(self, radix: u32) -> bool {
+        C::is_digit(self, radix)
+    }
 
-    /// Converts a character to the corresponding digit.
+    /// Converts a `char` to a digit in the given radix.
+    ///
+    /// A 'radix' here is sometimes also called a 'base'. A radix of two
+    /// indicates a binary number, a radix of ten, decimal, and a radix of
+    /// sixteen, hexicdecimal, to give some common values. Arbitrary
+    /// radicum are supported.
+    ///
+    /// 'Digit' is defined to be only the following characters:
+    ///
+    /// * `0-9`
+    /// * `a-z`
+    /// * `A-Z`
     ///
-    /// # Return value
+    /// # Failure
     ///
-    /// If `c` is between '0' and '9', the corresponding value between 0 and
-    /// 9. If `c` is 'a' or 'A', 10. If `c` is 'b' or 'B', 11, etc. Returns
-    /// none if the character does not refer to a digit in the given radix.
+    /// Returns `None` if the `char` does not refer to a digit in the given radix.
     ///
     /// # Panics
     ///
-    /// Panics if given a radix outside the range [0..36].
+    /// Panics if given a radix larger than 36.
     ///
     /// # Examples
     ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let d = '1';
+    ///
+    /// assert_eq!(d.to_digit(10), Some(1));
+    ///
+    /// let d = 'f';
+    ///
+    /// assert_eq!(d.to_digit(16), Some(15));
+    /// ```
+    ///
+    /// Passing a non-digit results in failure:
+    ///
+    /// ```
+    /// let d = 'f';
+    ///
+    /// assert_eq!(d.to_digit(10), None);
+    ///
+    /// let d = 'z';
+    ///
+    /// assert_eq!(d.to_digit(16), None);
+    /// ```
+    ///
+    /// Passing a large radix, causing a panic:
+    ///
     /// ```
-    /// let c = '1';
+    /// use std::thread;
     ///
-    /// assert_eq!(c.to_digit(10), Some(1));
+    /// let result = thread::spawn(|| {
+    ///   let d = '1';
     ///
-    /// assert_eq!('f'.to_digit(16), Some(15));
+    ///   d.to_digit(37);
+    /// }).join();
+    ///
+    /// assert!(result.is_err());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn to_digit(self, radix: u32) -> Option<u32> { C::to_digit(self, radix) }
+    pub fn to_digit(self, radix: u32) -> Option<u32> {
+        C::to_digit(self, radix)
+    }
 
     /// Returns an iterator that yields the hexadecimal Unicode escape of a
     /// character, as `char`s.
@@ -193,23 +270,33 @@ impl char {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn escape_unicode(self) -> EscapeUnicode { C::escape_unicode(self) }
+    pub fn escape_unicode(self) -> EscapeUnicode {
+        C::escape_unicode(self)
+    }
 
-    /// Returns an iterator that yields the 'default' ASCII and
-    /// C++11-like literal escape of a character, as `char`s.
+    /// Returns an iterator that yields the literal escape code of a `char`.
     ///
     /// The default is chosen with a bias toward producing literals that are
     /// legal in a variety of languages, including C++11 and similar C-family
     /// languages. The exact rules are:
     ///
-    /// * Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively.
-    /// * Single-quote, double-quote and backslash chars are backslash-
-    ///   escaped.
-    /// * Any other chars in the range [0x20,0x7e] are not escaped.
-    /// * Any other chars are given hex Unicode escapes; see `escape_unicode`.
+    /// * Tab is escaped as `\t`.
+    /// * Carriage return is escaped as `\r`.
+    /// * Line feed is escaped as `\n`.
+    /// * Single quote is escaped as `\'`.
+    /// * Double quote is escaped as `\"`.
+    /// * Backslash is escaped as `\\`.
+    /// * Any character in the 'printable ASCII' range `0x20` .. `0x7e`
+    ///   inclusive is not escaped.
+    /// * All other characters are given hexadecimal Unicode escapes; see
+    ///   [`escape_unicode`][escape_unicode].
+    ///
+    /// [escape_unicode]: #method.escape_unicode
     ///
     /// # Examples
     ///
+    /// Basic usage:
+    ///
     /// ```
     /// for i in '"'.escape_default() {
     ///     println!("{}", i);
@@ -232,35 +319,82 @@ impl char {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn escape_default(self) -> EscapeDefault { C::escape_default(self) }
+    pub fn escape_default(self) -> EscapeDefault {
+        C::escape_default(self)
+    }
 
-    /// Returns the number of bytes this character would need if encoded in
-    /// UTF-8.
+    /// Returns the number of bytes this `char` would need if encoded in UTF-8.
+    ///
+    /// That number of bytes is always between 1 and 4, inclusive.
     ///
     /// # Examples
     ///
+    /// Basic usage:
+    ///
     /// ```
-    /// let n = 'ß'.len_utf8();
+    /// let len = 'A'.len_utf8();
+    /// assert_eq!(len, 1);
+    ///
+    /// let len = 'ß'.len_utf8();
+    /// assert_eq!(len, 2);
+    ///
+    /// let len = 'ℝ'.len_utf8();
+    /// assert_eq!(len, 3);
     ///
-    /// assert_eq!(n, 2);
+    /// let len = '💣'.len_utf8();
+    /// assert_eq!(len, 4);
+    /// ```
+    ///
+    /// The `&str` type guarantees that its contents are UTF-8, and so we can compare the length it
+    /// would take if each code point was represented as a `char` vs in the `&str` itself:
+    ///
+    /// ```
+    /// // as chars
+    /// let eastern = '東';
+    /// let capitol = '京';
+    ///
+    /// // both can be represented as three bytes
+    /// assert_eq!(3, eastern.len_utf8());
+    /// assert_eq!(3, capitol.len_utf8());
+    ///
+    /// // as a &str, these two are encoded in UTF-8
+    /// let tokyo = "東京";
+    ///
+    /// let len = eastern.len_utf8() + capitol.len_utf8();
+    ///
+    /// // we can see that they take six bytes total...
+    /// assert_eq!(6, tokyo.len());
+    ///
+    /// // ... just like the &str
+    /// assert_eq!(len, tokyo.len());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn len_utf8(self) -> usize { C::len_utf8(self) }
+    pub fn len_utf8(self) -> usize {
+        C::len_utf8(self)
+    }
 
-    /// Returns the number of 16-bit code units this character would need if
+    /// Returns the number of 16-bit code units this `char` would need if
     /// encoded in UTF-16.
     ///
+    /// See the documentation for [`len_utf8()`][len_utf8] for more explanation
+    /// of this concept. This function is a mirror, but for UTF-16 instead of
+    /// UTF-8.
+    ///
     /// # Examples
     ///
     /// ```
     /// let n = 'ß'.len_utf16();
-    ///
     /// assert_eq!(n, 1);
+    ///
+    /// let len = '💣'.len_utf16();
+    /// assert_eq!(len, 2);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn len_utf16(self) -> usize { C::len_utf16(self) }
+    pub fn len_utf16(self) -> usize {
+        C::len_utf16(self)
+    }
 
     /// Encodes this character as UTF-8 into the provided byte buffer, and then
     /// returns the number of bytes written.
@@ -342,32 +476,50 @@ impl char {
         C::encode_utf16(self, dst)
     }
 
-    /// Returns whether the specified character is considered a Unicode
-    /// alphabetic code point.
+    /// Returns true if this `char` is an alphabetic code point, and false if not.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let c = 'a';
+    ///
+    /// assert!(c.is_alphabetic());
+    ///
+    /// let c = '京';
+    /// assert!(c.is_alphabetic());
+    ///
+    /// let c = '💝';
+    /// // love is many things, but it is not alphabetic
+    /// assert!(!c.is_alphabetic());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn is_alphabetic(self) -> bool {
         match self {
-            'a' ... 'z' | 'A' ... 'Z' => true,
+            'a'...'z' | 'A'...'Z' => true,
             c if c > '\x7f' => derived_property::Alphabetic(c),
-            _ => false
+            _ => false,
         }
     }
 
-    /// Returns whether the specified character satisfies the 'XID_Start'
-    /// Unicode property.
+    /// Returns true if this `char` satisfies the 'XID_Start' Unicode property, and false
+    /// otherwise.
     ///
     /// 'XID_Start' is a Unicode Derived Property specified in
     /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
-    /// mostly similar to ID_Start but modified for closure under NFKx.
+    /// mostly similar to `ID_Start` but modified for closure under `NFKx`.
     #[unstable(feature = "unicode",
                reason = "mainly needed for compiler internals",
                issue = "0")]
     #[inline]
-    pub fn is_xid_start(self) -> bool { derived_property::XID_Start(self) }
+    pub fn is_xid_start(self) -> bool {
+        derived_property::XID_Start(self)
+    }
 
-    /// Returns whether the specified `char` satisfies the 'XID_Continue'
-    /// Unicode property.
+    /// Returns true if this `char` satisfies the 'XID_Continue' Unicode property, and false
+    /// otherwise.
     ///
     /// 'XID_Continue' is a Unicode Derived Property specified in
     /// [UAX #31](http://unicode.org/reports/tr31/#NFKC_Modifications),
@@ -376,93 +528,249 @@ impl char {
                reason = "mainly needed for compiler internals",
                issue = "0")]
     #[inline]
-    pub fn is_xid_continue(self) -> bool { derived_property::XID_Continue(self) }
+    pub fn is_xid_continue(self) -> bool {
+        derived_property::XID_Continue(self)
+    }
 
-    /// Indicates whether a character is in lowercase.
+    /// Returns true if this `char` is lowercase, and false otherwise.
     ///
-    /// This is defined according to the terms of the Unicode Derived Core
+    /// 'Lowercase' is defined according to the terms of the Unicode Derived Core
     /// Property `Lowercase`.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let c = 'a';
+    /// assert!(c.is_lowercase());
+    ///
+    /// let c = 'δ';
+    /// assert!(c.is_lowercase());
+    ///
+    /// let c = 'A';
+    /// assert!(!c.is_lowercase());
+    ///
+    /// let c = 'Δ';
+    /// assert!(!c.is_lowercase());
+    ///
+    /// // The various Chinese scripts do not have case, and so:
+    /// let c = '中';
+    /// assert!(!c.is_lowercase());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn is_lowercase(self) -> bool {
         match self {
-            'a' ... 'z' => true,
+            'a'...'z' => true,
             c if c > '\x7f' => derived_property::Lowercase(c),
-            _ => false
+            _ => false,
         }
     }
 
-    /// Indicates whether a character is in uppercase.
+    /// Returns true if this `char` is uppercase, and false otherwise.
     ///
-    /// This is defined according to the terms of the Unicode Derived Core
+    /// 'Uppercase' is defined according to the terms of the Unicode Derived Core
     /// Property `Uppercase`.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let c = 'a';
+    /// assert!(!c.is_uppercase());
+    ///
+    /// let c = 'δ';
+    /// assert!(!c.is_uppercase());
+    ///
+    /// let c = 'A';
+    /// assert!(c.is_uppercase());
+    ///
+    /// let c = 'Δ';
+    /// assert!(c.is_uppercase());
+    ///
+    /// // The various Chinese scripts do not have case, and so:
+    /// let c = '中';
+    /// assert!(!c.is_uppercase());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn is_uppercase(self) -> bool {
         match self {
-            'A' ... 'Z' => true,
+            'A'...'Z' => true,
             c if c > '\x7f' => derived_property::Uppercase(c),
-            _ => false
+            _ => false,
         }
     }
 
-    /// Indicates whether a character is whitespace.
+    /// Returns true if this `char` is whitespace, and false otherwise.
+    ///
+    /// 'Whitespace' is defined according to the terms of the Unicode Derived Core
+    /// Property `White_Space`.
+    ///
+    /// # Examples
     ///
-    /// Whitespace is defined in terms of the Unicode Property `White_Space`.
+    /// Basic usage:
+    ///
+    /// ```
+    /// let c = ' ';
+    /// assert!(c.is_whitespace());
+    ///
+    /// // a non-breaking space
+    /// let c = '\u{A0}';
+    /// assert!(c.is_whitespace());
+    ///
+    /// let c = '越';
+    /// assert!(!c.is_whitespace());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn is_whitespace(self) -> bool {
         match self {
-            ' ' | '\x09' ... '\x0d' => true,
+            ' ' | '\x09'...'\x0d' => true,
             c if c > '\x7f' => property::White_Space(c),
-            _ => false
+            _ => false,
         }
     }
 
-    /// Indicates whether a character is alphanumeric.
+    /// Returns true if this `char` is alphanumeric, and false otherwise.
     ///
-    /// Alphanumericness is defined in terms of the Unicode General Categories
+    /// 'Alphanumeric'-ness is defined in terms of the Unicode General Categories
     /// 'Nd', 'Nl', 'No' and the Derived Core Property 'Alphabetic'.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let c = '٣';
+    /// assert!(c.is_alphanumeric());
+    ///
+    /// let c = '7';
+    /// assert!(c.is_alphanumeric());
+    ///
+    /// let c = '৬';
+    /// assert!(c.is_alphanumeric());
+    ///
+    /// let c = 'K';
+    /// assert!(c.is_alphanumeric());
+    ///
+    /// let c = 'و';
+    /// assert!(c.is_alphanumeric());
+    ///
+    /// let c = '藏';
+    /// assert!(c.is_alphanumeric());
+    ///
+    /// let c = '¾';
+    /// assert!(!c.is_alphanumeric());
+    ///
+    /// let c = '①';
+    /// assert!(!c.is_alphanumeric());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn is_alphanumeric(self) -> bool {
         self.is_alphabetic() || self.is_numeric()
     }
 
-    /// Indicates whether a character is a control code point.
+    /// Returns true if this `char` is a control code point, and false otherwise.
     ///
-    /// Control code points are defined in terms of the Unicode General
+    /// 'Control code point' is defined in terms of the Unicode General
     /// Category `Cc`.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// // U+009C, STRING TERMINATOR
+    /// let c = '\9c';
+    /// assert!(c.is_control());
+    ///
+    /// let c = 'q';
+    /// assert!(!c.is_control());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    pub fn is_control(self) -> bool { general_category::Cc(self) }
+    pub fn is_control(self) -> bool {
+        general_category::Cc(self)
+    }
 
-    /// Indicates whether the character is numeric (Nd, Nl, or No).
+    /// Returns true if this `char` is numeric, and false otherwise.
+    ///
+    /// 'Numeric'-ness is defined in terms of the Unicode General Categories
+    /// 'Nd', 'Nl', 'No'.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let c = '٣';
+    /// assert!(c.is_numeric());
+    ///
+    /// let c = '7';
+    /// assert!(c.is_numeric());
+    ///
+    /// let c = '৬';
+    /// assert!(c.is_numeric());
+    ///
+    /// let c = 'K';
+    /// assert!(!c.is_numeric());
+    ///
+    /// let c = 'و';
+    /// assert!(!c.is_numeric());
+    ///
+    /// let c = '藏';
+    /// assert!(!c.is_numeric());
+    ///
+    /// let c = '¾';
+    /// assert!(!c.is_numeric());
+    ///
+    /// let c = '①';
+    /// assert!(!c.is_numeric());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn is_numeric(self) -> bool {
         match self {
-            '0' ... '9' => true,
+            '0'...'9' => true,
             c if c > '\x7f' => general_category::N(c),
-            _ => false
+            _ => false,
         }
     }
 
-    /// Converts a character to its lowercase equivalent.
+    /// Returns an iterator that yields the lowercase equivalent of a `char`.
     ///
-    /// This performs complex unconditional mappings with no tailoring.
-    /// See `to_uppercase()` for references and more information.
+    /// If no conversion is possible then an iterator with just the input character is returned.
     ///
-    /// # Return value
+    /// This performs complex unconditional mappings with no tailoring: it maps
+    /// one Unicode character to its lowercase equivalent according to the
+    /// [Unicode database] and the additional complex mappings
+    /// [`SpecialCasing.txt`]. Conditional mappings (based on context or
+    /// language) are not considered here.
     ///
-    /// Returns an iterator which yields the characters corresponding to the
-    /// lowercase equivalent of the character. If no conversion is possible then
-    /// an iterator with just the input character is returned.
+    /// For a full reference, see [here][reference].
+    ///
+    /// [Unicode database]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
+    ///
+    /// [`SpecialCasing.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
+    ///
+    /// [reference]: http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992
     ///
     /// # Examples
     ///
+    /// Basic usage:
+    ///
     /// ```
-    /// assert_eq!(Some('c'), 'C'.to_lowercase().next());
+    /// let c = 'c';
+    ///
+    /// assert_eq!(c.to_uppercase().next(), Some('C'));
+    ///
+    /// // Japanese scripts do not have case, and so:
+    /// let c = '山';
+    /// assert_eq!(c.to_uppercase().next(), Some('山'));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -470,33 +778,63 @@ impl char {
         ToLowercase(CaseMappingIter::new(conversions::to_lower(self)))
     }
 
-    /// Converts a character to its uppercase equivalent.
-    ///
-    /// This performs complex unconditional mappings with no tailoring:
-    /// it maps one Unicode character to its uppercase equivalent
-    /// according to the Unicode database [1]
-    /// and the additional complex mappings [`SpecialCasing.txt`].
-    /// Conditional mappings (based on context or language) are not considered here.
+    /// Returns an iterator that yields the uppercase equivalent of a `char`.
     ///
-    /// A full reference can be found here [2].
+    /// If no conversion is possible then an iterator with just the input character is returned.
     ///
-    /// # Return value
+    /// This performs complex unconditional mappings with no tailoring: it maps
+    /// one Unicode character to its uppercase equivalent according to the
+    /// [Unicode database] and the additional complex mappings
+    /// [`SpecialCasing.txt`]. Conditional mappings (based on context or
+    /// language) are not considered here.
     ///
-    /// Returns an iterator which yields the characters corresponding to the
-    /// uppercase equivalent of the character. If no conversion is possible then
-    /// an iterator with just the input character is returned.
+    /// For a full reference, see [here][reference].
     ///
-    /// [1]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
+    /// [Unicode database]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
     ///
     /// [`SpecialCasing.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt
     ///
-    /// [2]: http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992
+    /// [reference]: http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992
     ///
     /// # Examples
     ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let c = 'c';
+    /// assert_eq!(c.to_uppercase().next(), Some('C'));
+    ///
+    /// // Japanese does not have case, and so:
+    /// let c = '山';
+    /// assert_eq!(c.to_uppercase().next(), Some('山'));
+    /// ```
+    ///
+    /// In Turkish, the equivalent of 'i' in Latin has five forms instead of two:
+    ///
+    /// * 'Dotless': I / ı, sometimes written ï
+    /// * 'Dotted': İ / i
+    ///
+    /// Note that the lowercase dotted 'i' is the same as the Latin. Therefore:
+    ///
+    /// ```
+    /// let i = 'i';
+    ///
+    /// let upper_i = i.to_uppercase().next();
+    /// ```
+    ///
+    /// The value of `upper_i` here relies on the language of the text: if we're
+    /// in `en-US`, it should be `Some('I')`, but if we're in `tr_TR`, it should
+    /// be `Some('İ')`. `to_uppercase()` does not take this into account, and so:
+    ///
     /// ```
-    /// assert_eq!(Some('C'), 'c'.to_uppercase().next());
+    /// let i = 'i';
+    ///
+    /// let upper_i = i.to_uppercase().next();
+    ///
+    /// assert_eq!(Some('I'), upper_i);
     /// ```
+    ///
+    /// holds across languages.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn to_uppercase(self) -> ToUppercase {
@@ -504,15 +842,17 @@ impl char {
     }
 }
 
-/// An iterator that decodes UTF-16 encoded codepoints from an iterator of `u16`s.
+/// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s.
 #[unstable(feature = "decode_utf16", reason = "recently exposed", issue = "27830")]
 #[derive(Clone)]
-pub struct DecodeUtf16<I> where I: Iterator<Item=u16> {
+pub struct DecodeUtf16<I>
+    where I: Iterator<Item = u16>
+{
     iter: I,
     buf: Option<u16>,
 }
 
-/// Create an iterator over the UTF-16 encoded codepoints in `iterable`,
+/// Create an iterator over the UTF-16 encoded code points in `iterable`,
 /// returning unpaired surrogates as `Err`s.
 ///
 /// # Examples
@@ -558,7 +898,7 @@ pub struct DecodeUtf16<I> where I: Iterator<Item=u16> {
 /// ```
 #[unstable(feature = "decode_utf16", reason = "recently exposed", issue = "27830")]
 #[inline]
-pub fn decode_utf16<I: IntoIterator<Item=u16>>(iterable: I) -> DecodeUtf16<I::IntoIter> {
+pub fn decode_utf16<I: IntoIterator<Item = u16>>(iterable: I) -> DecodeUtf16<I::IntoIter> {
     DecodeUtf16 {
         iter: iterable.into_iter(),
         buf: None,
@@ -574,8 +914,8 @@ impl<I: Iterator<Item=u16>> Iterator for DecodeUtf16<I> {
             Some(buf) => buf,
             None => match self.iter.next() {
                 Some(u) => u,
-                None => return None
-            }
+                None => return None,
+            },
         };
 
         if u < 0xD800 || 0xDFFF < u {
@@ -588,13 +928,13 @@ impl<I: Iterator<Item=u16>> Iterator for DecodeUtf16<I> {
             let u2 = match self.iter.next() {
                 Some(u2) => u2,
                 // eof
-                None => return Some(Err(u))
+                None => return Some(Err(u)),
             };
             if u2 < 0xDC00 || u2 > 0xDFFF {
                 // not a trailing surrogate so we're not a valid
                 // surrogate pair, so rewind to redecode u2 next time.
                 self.buf = Some(u2);
-                return Some(Err(u))
+                return Some(Err(u));
             }
 
             // all ok, so lets decode it.
@@ -612,7 +952,8 @@ impl<I: Iterator<Item=u16>> Iterator for DecodeUtf16<I> {
     }
 }
 
-/// U+FFFD REPLACEMENT CHARACTER (�) is used in Unicode to represent a decoding error.
-/// It can occur, for example, when giving ill-formed UTF-8 bytes to `String::from_utf8_lossy`.
+/// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a decoding error.
+/// It can occur, for example, when giving ill-formed UTF-8 bytes to
+/// [`String::from_utf8_lossy`](../string/struct.String.html#method.from_utf8_lossy).
 #[unstable(feature = "decode_utf16", reason = "recently added", issue = "27830")]
 pub const REPLACEMENT_CHARACTER: char = '\u{FFFD}';
index 4f0aa69d7719930e6811d4224b71bd577a05730e..467c974690062e70ab934a4efd771a916f8f7653 100644 (file)
@@ -34,7 +34,6 @@
        test(no_crate_inject))]
 #![no_std]
 
-#![feature(char_from_unchecked)]
 #![feature(core_char_ext)]
 #![feature(core_slice_ext)]
 #![feature(core_str_ext)]
index 67333c98fcf84bc5dd40e63fc6a323225995d3cf..2347cdebf2292e60ed550ccc33614c5dced79fb8 100644 (file)
@@ -10,8 +10,8 @@
 
 //! Unicode-intensive string manipulations.
 //!
-//! This module provides functionality to `str` that requires the Unicode methods provided by the
-//! unicode parts of the CharExt trait.
+//! This module provides functionality to `str` that requires the Unicode
+//! methods provided by the unicode parts of the CharExt trait.
 
 use char::{DecodeUtf16, decode_utf16};
 use core::char;
@@ -40,20 +40,28 @@ pub trait UnicodeStr {
 impl UnicodeStr for str {
     #[inline]
     fn split_whitespace(&self) -> SplitWhitespace {
-        fn is_not_empty(s: &&str) -> bool { !s.is_empty() }
+        fn is_not_empty(s: &&str) -> bool {
+            !s.is_empty()
+        }
         let is_not_empty: fn(&&str) -> bool = is_not_empty; // coerce to fn pointer
 
-        fn is_whitespace(c: char) -> bool { c.is_whitespace() }
+        fn is_whitespace(c: char) -> bool {
+            c.is_whitespace()
+        }
         let is_whitespace: fn(char) -> bool = is_whitespace; // coerce to fn pointer
 
         SplitWhitespace { inner: self.split(is_whitespace).filter(is_not_empty) }
     }
 
     #[inline]
-    fn is_whitespace(&self) -> bool { self.chars().all(|c| c.is_whitespace()) }
+    fn is_whitespace(&self) -> bool {
+        self.chars().all(|c| c.is_whitespace())
+    }
 
     #[inline]
-    fn is_alphanumeric(&self) -> bool { self.chars().all(|c| c.is_alphanumeric()) }
+    fn is_alphanumeric(&self) -> bool {
+        self.chars().all(|c| c.is_alphanumeric())
+    }
 
     #[inline]
     fn trim(&self) -> &str {
@@ -111,8 +119,9 @@ pub fn is_utf16(v: &[u16]) -> bool {
             Some(_) => {}
             None => {
                 let u2 = next!(false);
-                if u < 0xD7FF || u > 0xDBFF ||
-                    u2 < 0xDC00 || u2 > 0xDFFF { return false; }
+                if u < 0xD7FF || u > 0xDBFF || u2 < 0xDC00 || u2 > 0xDFFF {
+                    return false;
+                }
             }
         }
     }
@@ -125,7 +134,7 @@ pub fn is_utf16(v: &[u16]) -> bool {
 #[allow(deprecated)]
 #[derive(Clone)]
 pub struct Utf16Items<'a> {
-    decoder: DecodeUtf16<Cloned<slice::Iter<'a, u16>>>
+    decoder: DecodeUtf16<Cloned<slice::Iter<'a, u16>>>,
 }
 
 /// The possibilities for values decoded from a `u16` stream.
@@ -137,7 +146,7 @@ pub enum Utf16Item {
     /// A valid codepoint.
     ScalarValue(char),
     /// An invalid surrogate without its pair.
-    LoneSurrogate(u16)
+    LoneSurrogate(u16),
 }
 
 #[allow(deprecated)]
@@ -148,7 +157,7 @@ impl Utf16Item {
     pub fn to_char_lossy(&self) -> char {
         match *self {
             Utf16Item::ScalarValue(c) => c,
-            Utf16Item::LoneSurrogate(_) => '\u{FFFD}'
+            Utf16Item::LoneSurrogate(_) => '\u{FFFD}',
         }
     }
 }
@@ -160,9 +169,11 @@ impl<'a> Iterator for Utf16Items<'a> {
     type Item = Utf16Item;
 
     fn next(&mut self) -> Option<Utf16Item> {
-        self.decoder.next().map(|result| match result {
-            Ok(c) => Utf16Item::ScalarValue(c),
-            Err(s) => Utf16Item::LoneSurrogate(s),
+        self.decoder.next().map(|result| {
+            match result {
+                Ok(c) => Utf16Item::ScalarValue(c),
+                Err(s) => Utf16Item::LoneSurrogate(s),
+            }
         })
     }
 
@@ -209,13 +220,18 @@ pub fn utf16_items<'a>(v: &'a [u16]) -> Utf16Items<'a> {
 #[derive(Clone)]
 pub struct Utf16Encoder<I> {
     chars: I,
-    extra: u16
+    extra: u16,
 }
 
 impl<I> Utf16Encoder<I> {
     /// Create a UTF-16 encoder from any `char` iterator.
-    pub fn new(chars: I) -> Utf16Encoder<I> where I: Iterator<Item=char> {
-        Utf16Encoder { chars: chars, extra: 0 }
+    pub fn new(chars: I) -> Utf16Encoder<I>
+        where I: Iterator<Item = char>
+    {
+        Utf16Encoder {
+            chars: chars,
+            extra: 0,
+        }
     }
 }
 
@@ -233,7 +249,9 @@ impl<I> Iterator for Utf16Encoder<I> where I: Iterator<Item=char> {
         let mut buf = [0; 2];
         self.chars.next().map(|ch| {
             let n = CharExt::encode_utf16(ch, &mut buf).unwrap_or(0);
-            if n == 2 { self.extra = buf[1]; }
+            if n == 2 {
+                self.extra = buf[1];
+            }
             buf[0]
         })
     }
@@ -251,8 +269,12 @@ impl<I> Iterator for Utf16Encoder<I> where I: Iterator<Item=char> {
 impl<'a> Iterator for SplitWhitespace<'a> {
     type Item = &'a str;
 
-    fn next(&mut self) -> Option<&'a str> { self.inner.next() }
+    fn next(&mut self) -> Option<&'a str> {
+        self.inner.next()
+    }
 }
 impl<'a> DoubleEndedIterator for SplitWhitespace<'a> {
-    fn next_back(&mut self) -> Option<&'a str> { self.inner.next_back() }
+    fn next_back(&mut self) -> Option<&'a str> {
+        self.inner.next_back()
+    }
 }
index c9af86f06db9325ee1ca4d7c96929767b7ca51ba..ee772411c4e9af85b8b8ce01b8c385a546d4ee06 100644 (file)
@@ -13,7 +13,7 @@
 use std::collections::HashSet;
 
 use syntax::ast;
-use rustc_front::attr::AttrMetaMethods;
+use syntax::attr::AttrMetaMethods;
 use rustc_front::hir;
 
 use rustc::metadata::csearch;
@@ -43,7 +43,7 @@ use super::{Clean, ToSource};
 ///
 /// The returned value is `None` if the `id` could not be inlined, and `Some`
 /// of a vector of items if it was successfully expanded.
-pub fn try_inline(cx: &DocContext, id: ast::NodeId, into: Option<ast::Ident>)
+pub fn try_inline(cx: &DocContext, id: ast::NodeId, into: Option<ast::Name>)
                   -> Option<Vec<clean::Item>> {
     let tcx = match cx.tcx_opt() {
         Some(tcx) => tcx,
@@ -317,10 +317,11 @@ pub fn build_impl(cx: &DocContext,
             ty::ConstTraitItem(ref assoc_const) => {
                 let did = assoc_const.def_id;
                 let type_scheme = tcx.lookup_item_type(did);
-                let default = match assoc_const.default {
-                    Some(_) => Some(const_eval::lookup_const_by_id(tcx, did, None)
-                                               .unwrap().span.to_src(cx)),
-                    None => None,
+                let default = if assoc_const.has_value {
+                    Some(const_eval::lookup_const_by_id(tcx, did, None)
+                         .unwrap().span.to_src(cx))
+                } else {
+                    None
                 };
                 Some(clean::Item {
                     name: Some(assoc_const.name.clean(cx)),
@@ -339,9 +340,6 @@ pub fn build_impl(cx: &DocContext,
                 if method.vis != hir::Public && associated_trait.is_none() {
                     return None
                 }
-                if method.provided_source.is_some() {
-                    return None
-                }
                 let mut item = method.clean(cx);
                 item.inner = match item.inner.clone() {
                     clean::TyMethodItem(clean::TyMethod {
index 7ef359787e87e1b6438e9737f85af75785e0d069..75144ff27b0a732ad669b2d66e2750abeb9d6a7d 100644 (file)
@@ -27,6 +27,8 @@ pub use self::FunctionRetTy::*;
 use syntax;
 use syntax::abi;
 use syntax::ast;
+use syntax::attr;
+use syntax::attr::{AttributeMethods, AttrMetaMethods};
 use syntax::codemap;
 use syntax::codemap::{DUMMY_SP, Pos, Spanned};
 use syntax::parse::token::{self, InternedString, special_idents};
@@ -37,15 +39,12 @@ use rustc::metadata::cstore;
 use rustc::metadata::csearch;
 use rustc::metadata::decoder;
 use rustc::middle::def;
-use rustc::middle::def_id::{DefId, LOCAL_CRATE};
+use rustc::middle::def_id::{DefId, DefIndex};
 use rustc::middle::subst::{self, ParamSpace, VecPerParamSpace};
 use rustc::middle::ty;
 use rustc::middle::stability;
 
 use rustc_front::hir;
-use rustc_front::attr;
-use rustc_front::attr::{AttributeMethods, AttrMetaMethods};
-use rustc_front::lowering::unlower_attribute;
 
 use std::collections::HashMap;
 use std::path::PathBuf;
@@ -143,8 +142,7 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
 
         // Figure out the name of this crate
         let input = &cx.input;
-        let attrs: Vec<_> = self.attrs.iter().map(|a| unlower_attribute(a)).collect();
-        let name = link::find_crate_name(None, &attrs, input);
+        let name = link::find_crate_name(None, &self.attrs, input);
 
         // Clean the crate, translating the entire libsyntax AST to one that is
         // understood by rustdoc.
@@ -155,7 +153,7 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
         //
         // Note that this loop only searches the top-level items of the crate,
         // and this is intentional. If we were to search the entire crate for an
-        // item tagged with `#[doc(primitive)]` then we we would also have to
+        // item tagged with `#[doc(primitive)]` then we would also have to
         // search the entirety of external modules for items tagged
         // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
         // all that metadata unconditionally).
@@ -190,7 +188,7 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> {
                     attrs: child.attrs.clone(),
                     visibility: Some(hir::Public),
                     stability: None,
-                    def_id: DefId::local(prim.to_node_id()),
+                    def_id: DefId::local(prim.to_def_index()),
                     inner: PrimitiveItem(prim),
                 });
             }
@@ -326,8 +324,8 @@ impl Item {
         match self.stability {
             Some(ref s) => {
                 let mut base = match s.level {
-                    attr::Unstable => "unstable".to_string(),
-                    attr::Stable => String::new(),
+                    stability::Unstable => "unstable".to_string(),
+                    stability::Stable => String::new(),
                 };
                 if !s.deprecated_since.is_empty() {
                     base.push_str(" deprecated");
@@ -421,7 +419,7 @@ impl Clean<Item> for doctree::Module {
             source: whence.clean(cx),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
-            def_id: DefId::local(self.id),
+            def_id: cx.map.local_def_id(self.id),
             inner: ModuleItem(Module {
                is_crate: self.is_crate,
                items: items
@@ -437,21 +435,21 @@ pub enum Attribute {
     NameValue(String, String)
 }
 
-impl Clean<Attribute> for hir::MetaItem {
+impl Clean<Attribute> for ast::MetaItem {
     fn clean(&self, cx: &DocContext) -> Attribute {
         match self.node {
-            hir::MetaWord(ref s) => Word(s.to_string()),
-            hir::MetaList(ref s, ref l) => {
+            ast::MetaWord(ref s) => Word(s.to_string()),
+            ast::MetaList(ref s, ref l) => {
                 List(s.to_string(), l.clean(cx))
             }
-            hir::MetaNameValue(ref s, ref v) => {
+            ast::MetaNameValue(ref s, ref v) => {
                 NameValue(s.to_string(), lit_to_string(v))
             }
         }
     }
 }
 
-impl Clean<Attribute> for hir::Attribute {
+impl Clean<Attribute> for ast::Attribute {
     fn clean(&self, cx: &DocContext) -> Attribute {
         self.with_desugared_doc(|a| a.node.value.clean(cx))
     }
@@ -475,13 +473,13 @@ impl attr::AttrMetaMethods for Attribute {
             _ => None,
         }
     }
-    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<hir::MetaItem>]> { None }
+    fn meta_item_list<'a>(&'a self) -> Option<&'a [P<ast::MetaItem>]> { None }
     fn span(&self) -> codemap::Span { unimplemented!() }
 }
 impl<'a> attr::AttrMetaMethods for &'a Attribute {
     fn name(&self) -> InternedString { (**self).name() }
     fn value_str(&self) -> Option<InternedString> { (**self).value_str() }
-    fn meta_item_list(&self) -> Option<&[P<hir::MetaItem>]> { None }
+    fn meta_item_list(&self) -> Option<&[P<ast::MetaItem>]> { None }
     fn span(&self) -> codemap::Span { unimplemented!() }
 }
 
@@ -496,8 +494,8 @@ pub struct TyParam {
 impl Clean<TyParam> for hir::TyParam {
     fn clean(&self, cx: &DocContext) -> TyParam {
         TyParam {
-            name: self.ident.clean(cx),
-            did: DefId { krate: LOCAL_CRATE, node: self.id },
+            name: self.name.clean(cx),
+            did: cx.map.local_def_id(self.id),
             bounds: self.bounds.clean(cx),
             default: self.default.clean(cx),
         }
@@ -1089,7 +1087,7 @@ impl Clean<Item> for doctree::Function {
             source: self.whence.clean(cx),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
-            def_id: DefId::local(self.id),
+            def_id: cx.map.local_def_id(self.id),
             inner: FunctionItem(Function {
                 decl: self.decl.clean(cx),
                 generics: self.generics.clean(cx),
@@ -1139,10 +1137,10 @@ impl<'tcx> Clean<Type> for ty::FnOutput<'tcx> {
 impl<'a, 'tcx> Clean<FnDecl> for (DefId, &'a ty::PolyFnSig<'tcx>) {
     fn clean(&self, cx: &DocContext) -> FnDecl {
         let (did, sig) = *self;
-        let mut names = if did.node != 0 {
-            csearch::get_method_arg_names(&cx.tcx().sess.cstore, did).into_iter()
+        let mut names = if let Some(_) = cx.map.as_local_node_id(did) {
+            vec![].into_iter()
         } else {
-            Vec::new().into_iter()
+            csearch::get_method_arg_names(&cx.tcx().sess.cstore, did).into_iter()
         }.peekable();
         if names.peek().map(|s| &**s) == Some("self") {
             let _ = names.next();
@@ -1212,7 +1210,7 @@ impl Clean<Item> for doctree::Trait {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: DefId::local(self.id),
+            def_id: cx.map.local_def_id(self.id),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
             inner: TraitItem(Trait {
@@ -1259,12 +1257,12 @@ impl Clean<Item> for hir::TraitItem {
             }
         };
         Item {
-            name: Some(self.ident.clean(cx)),
+            name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.span.clean(cx),
-            def_id: DefId::local(self.id),
+            def_id: cx.map.local_def_id(self.id),
             visibility: None,
-            stability: get_stability(cx, DefId::local(self.id)),
+            stability: get_stability(cx, cx.map.local_def_id(self.id)),
             inner: inner
         }
     }
@@ -1292,12 +1290,12 @@ impl Clean<Item> for hir::ImplItem {
             }, true),
         };
         Item {
-            name: Some(self.ident.clean(cx)),
+            name: Some(self.name.clean(cx)),
             source: self.span.clean(cx),
             attrs: self.attrs.clean(cx),
-            def_id: DefId::local(self.id),
+            def_id: cx.map.local_def_id(self.id),
             visibility: self.vis.clean(cx),
-            stability: get_stability(cx, DefId::local(self.id)),
+            stability: get_stability(cx, cx.map.local_def_id(self.id)),
             inner: inner
         }
     }
@@ -1561,8 +1559,9 @@ impl PrimitiveType {
     /// Creates a rustdoc-specific node id for primitive types.
     ///
     /// These node ids are generally never used by the AST itself.
-    pub fn to_node_id(&self) -> ast::NodeId {
-        u32::MAX - 1 - (*self as u32)
+    pub fn to_def_index(&self) -> DefIndex {
+        let x = u32::MAX - 1 - (*self as u32);
+        DefIndex::new(x as usize)
     }
 }
 
@@ -1585,7 +1584,7 @@ impl Clean<Type> for hir::Ty {
                 let mut trait_path = p.clone();
                 trait_path.segments.pop();
                 Type::QPath {
-                    name: p.segments.last().unwrap().identifier.clean(cx),
+                    name: p.segments.last().unwrap().identifier.name.clean(cx),
                     self_type: box qself.ty.clean(cx),
                     trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
                 }
@@ -1626,18 +1625,18 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
         match self.sty {
             ty::TyBool => Primitive(Bool),
             ty::TyChar => Primitive(Char),
-            ty::TyInt(hir::TyIs) => Primitive(Isize),
-            ty::TyInt(hir::TyI8) => Primitive(I8),
-            ty::TyInt(hir::TyI16) => Primitive(I16),
-            ty::TyInt(hir::TyI32) => Primitive(I32),
-            ty::TyInt(hir::TyI64) => Primitive(I64),
-            ty::TyUint(hir::TyUs) => Primitive(Usize),
-            ty::TyUint(hir::TyU8) => Primitive(U8),
-            ty::TyUint(hir::TyU16) => Primitive(U16),
-            ty::TyUint(hir::TyU32) => Primitive(U32),
-            ty::TyUint(hir::TyU64) => Primitive(U64),
-            ty::TyFloat(hir::TyF32) => Primitive(F32),
-            ty::TyFloat(hir::TyF64) => Primitive(F64),
+            ty::TyInt(ast::TyIs) => Primitive(Isize),
+            ty::TyInt(ast::TyI8) => Primitive(I8),
+            ty::TyInt(ast::TyI16) => Primitive(I16),
+            ty::TyInt(ast::TyI32) => Primitive(I32),
+            ty::TyInt(ast::TyI64) => Primitive(I64),
+            ty::TyUint(ast::TyUs) => Primitive(Usize),
+            ty::TyUint(ast::TyU8) => Primitive(U8),
+            ty::TyUint(ast::TyU16) => Primitive(U16),
+            ty::TyUint(ast::TyU32) => Primitive(U32),
+            ty::TyUint(ast::TyU64) => Primitive(U64),
+            ty::TyFloat(ast::TyF32) => Primitive(F32),
+            ty::TyFloat(ast::TyF64) => Primitive(F64),
             ty::TyStr => Primitive(Str),
             ty::TyBox(t) => {
                 let box_did = cx.tcx_opt().and_then(|tcx| {
@@ -1661,7 +1660,7 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
                     type_params: Vec::new(),
                     where_predicates: Vec::new()
                 },
-                decl: (DefId::local(0), &fty.sig).clean(cx),
+                decl: (cx.map.local_def_id(0), &fty.sig).clean(cx),
                 abi: fty.abi.to_string(),
             }),
             ty::TyStruct(def, substs) |
@@ -1729,8 +1728,8 @@ impl Clean<Item> for hir::StructField {
             attrs: self.node.attrs.clean(cx),
             source: self.span.clean(cx),
             visibility: Some(vis),
-            stability: get_stability(cx, DefId::local(self.node.id)),
-            def_id: DefId::local(self.node.id),
+            stability: get_stability(cx, cx.map.local_def_id(self.node.id)),
+            def_id: cx.map.local_def_id(self.node.id),
             inner: StructFieldItem(TypedStructField(self.node.ty.clean(cx))),
         }
     }
@@ -1746,7 +1745,7 @@ impl<'tcx> Clean<Item> for ty::FieldDefData<'tcx, 'static> {
         let (name, attrs) = if self.name == unnamed_field.name {
             (None, None)
         } else {
-            (Some(self.name), Some(attr_map.get(&self.did.node).unwrap()))
+            (Some(self.name), Some(attr_map.get(&self.did).unwrap()))
         };
 
         Item {
@@ -1783,7 +1782,7 @@ impl Clean<Item> for doctree::Struct {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: DefId::local(self.id),
+            def_id: cx.map.local_def_id(self.id),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
             inner: StructItem(Struct {
@@ -1806,11 +1805,11 @@ pub struct VariantStruct {
     pub fields_stripped: bool,
 }
 
-impl Clean<VariantStruct> for ::rustc_front::hir::StructDef {
+impl Clean<VariantStruct> for ::rustc_front::hir::VariantData {
     fn clean(&self, cx: &DocContext) -> VariantStruct {
         VariantStruct {
             struct_type: doctree::struct_type_from_def(self),
-            fields: self.fields.clean(cx),
+            fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
             fields_stripped: false,
         }
     }
@@ -1829,7 +1828,7 @@ impl Clean<Item> for doctree::Enum {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: DefId::local(self.id),
+            def_id: cx.map.local_def_id(self.id),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
             inner: EnumItem(Enum {
@@ -1852,11 +1851,11 @@ impl Clean<Item> for doctree::Variant {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            visibility: self.vis.clean(cx),
+            visibility: None,
             stability: self.stab.clean(cx),
-            def_id: DefId::local(self.id),
+            def_id: cx.map.local_def_id(self.def.id()),
             inner: VariantItem(Variant {
-                kind: self.kind.clean(cx),
+                kind: struct_def_to_variant_kind(&self.def, cx),
             }),
         }
     }
@@ -1872,7 +1871,7 @@ impl<'tcx> Clean<Item> for ty::VariantDefData<'tcx, 'static> {
                     self.fields.iter().map(|f| f.unsubst_ty().clean(cx)).collect()
                 )
             }
-            ty::VariantKind::Dict => {
+            ty::VariantKind::Struct => {
                 StructVariant(VariantStruct {
                     struct_type: doctree::Plain,
                     fields_stripped: false,
@@ -1918,18 +1917,13 @@ pub enum VariantKind {
     StructVariant(VariantStruct),
 }
 
-impl Clean<VariantKind> for hir::VariantKind {
-    fn clean(&self, cx: &DocContext) -> VariantKind {
-        match self {
-            &hir::TupleVariantKind(ref args) => {
-                if args.is_empty() {
-                    CLikeVariant
-                } else {
-                    TupleVariant(args.iter().map(|x| x.ty.clean(cx)).collect())
-                }
-            },
-            &hir::StructVariantKind(ref sd) => StructVariant(sd.clean(cx)),
-        }
+fn struct_def_to_variant_kind(struct_def: &hir::VariantData, cx: &DocContext) -> VariantKind {
+    if struct_def.is_struct() {
+        StructVariant(struct_def.clean(cx))
+    } else if struct_def.is_unit() {
+        CLikeVariant
+    } else {
+        TupleVariant(struct_def.fields().iter().map(|x| x.node.ty.clean(cx)).collect())
     }
 }
 
@@ -2046,7 +2040,7 @@ pub struct PathSegment {
 impl Clean<PathSegment> for hir::PathSegment {
     fn clean(&self, cx: &DocContext) -> PathSegment {
         PathSegment {
-            name: self.identifier.clean(cx),
+            name: self.identifier.name.clean(cx),
             params: self.parameters.clean(cx)
         }
     }
@@ -2066,12 +2060,6 @@ fn path_to_string(p: &hir::Path) -> String {
     s
 }
 
-impl Clean<String> for ast::Ident {
-    fn clean(&self, _: &DocContext) -> String {
-        self.to_string()
-    }
-}
-
 impl Clean<String> for ast::Name {
     fn clean(&self, _: &DocContext) -> String {
         self.to_string()
@@ -2090,7 +2078,7 @@ impl Clean<Item> for doctree::Typedef {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: DefId::local(self.id.clone()),
+            def_id: cx.map.local_def_id(self.id.clone()),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
             inner: TypedefItem(Typedef {
@@ -2141,7 +2129,7 @@ impl Clean<Item> for doctree::Static {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: DefId::local(self.id),
+            def_id: cx.map.local_def_id(self.id),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
             inner: StaticItem(Static {
@@ -2165,7 +2153,7 @@ impl Clean<Item> for doctree::Constant {
             name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: DefId::local(self.id),
+            def_id: cx.map.local_def_id(self.id),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
             inner: ConstantItem(Constant {
@@ -2239,7 +2227,7 @@ impl Clean<Vec<Item>> for doctree::Impl {
             name: None,
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: DefId::local(self.id),
+            def_id: cx.map.local_def_id(self.id),
             visibility: self.vis.clean(cx),
             stability: self.stab.clean(cx),
             inner: ImplItem(Impl {
@@ -2321,7 +2309,7 @@ impl Clean<Item> for doctree::DefaultImpl {
             name: None,
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: DefId::local(self.id),
+            def_id: cx.map.local_def_id(self.id),
             visibility: Some(hir::Public),
             stability: None,
             inner: DefaultImplItem(DefaultImpl {
@@ -2338,7 +2326,7 @@ impl Clean<Item> for doctree::ExternCrate {
             name: None,
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: DefId::local(0),
+            def_id: cx.map.local_def_id(0),
             visibility: self.vis.clean(cx),
             stability: None,
             inner: ExternCrateItem(self.name.clean(cx), self.path.clone())
@@ -2388,14 +2376,14 @@ impl Clean<Vec<Item>> for doctree::Import {
                 (ret, ImportList(resolve_use_source(cx, p.clean(cx), self.id),
                                  remaining))
             }
-            hir::ViewPathSimple(i, ref p) => {
+            hir::ViewPathSimple(name, ref p) => {
                 if !denied {
-                    match inline::try_inline(cx, self.id, Some(i)) {
+                    match inline::try_inline(cx, self.id, Some(name)) {
                         Some(items) => return items,
                         None => {}
                     }
                 }
-                (vec![], SimpleImport(i.clean(cx),
+                (vec![], SimpleImport(name.clean(cx),
                                       resolve_use_source(cx, p.clean(cx), self.id)))
             }
         };
@@ -2403,7 +2391,7 @@ impl Clean<Vec<Item>> for doctree::Import {
             name: None,
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: DefId::local(0),
+            def_id: cx.map.local_def_id(0),
             visibility: self.vis.clean(cx),
             stability: None,
             inner: ImportItem(inner)
@@ -2486,12 +2474,12 @@ impl Clean<Item> for hir::ForeignItem {
             }
         };
         Item {
-            name: Some(self.ident.clean(cx)),
+            name: Some(self.name.clean(cx)),
             attrs: self.attrs.clean(cx),
             source: self.span.clean(cx),
-            def_id: DefId::local(self.id),
+            def_id: cx.map.local_def_id(self.id),
             visibility: self.vis.clean(cx),
-            stability: get_stability(cx, DefId::local(self.id)),
+            stability: get_stability(cx, cx.map.local_def_id(self.id)),
             inner: inner,
         }
     }
@@ -2515,11 +2503,11 @@ impl ToSource for syntax::codemap::Span {
     }
 }
 
-fn lit_to_string(lit: &hir::Lit) -> String {
+fn lit_to_string(lit: &ast::Lit) -> String {
     match lit.node {
-        hir::LitStr(ref st, _) => st.to_string(),
-        hir::LitByteStr(ref data) => format!("{:?}", data),
-        hir::LitByte(b) => {
+        ast::LitStr(ref st, _) => st.to_string(),
+        ast::LitByteStr(ref data) => format!("{:?}", data),
+        ast::LitByte(b) => {
             let mut res = String::from("b'");
             for c in (b as char).escape_default() {
                 res.push(c);
@@ -2527,11 +2515,11 @@ fn lit_to_string(lit: &hir::Lit) -> String {
             res.push('\'');
             res
         },
-        hir::LitChar(c) => format!("'{}'", c),
-        hir::LitInt(i, _t) => i.to_string(),
-        hir::LitFloat(ref f, _t) => f.to_string(),
-        hir::LitFloatUnsuffixed(ref f) => f.to_string(),
-        hir::LitBool(b) => b.to_string(),
+        ast::LitChar(c) => format!("'{}'", c),
+        ast::LitInt(i, _t) => i.to_string(),
+        ast::LitFloat(ref f, _t) => f.to_string(),
+        ast::LitFloatUnsuffixed(ref f) => f.to_string(),
+        ast::LitBool(b) => b.to_string(),
     }
 }
 
@@ -2549,7 +2537,7 @@ fn name_from_pat(p: &hir::Pat) -> String {
         PatStruct(ref name, ref fields, etc) => {
             format!("{} {{ {}{} }}", path_to_string(name),
                 fields.iter().map(|&Spanned { node: ref fp, .. }|
-                                  format!("{}: {}", fp.ident, name_from_pat(&*fp.pat)))
+                                  format!("{}: {}", fp.name, name_from_pat(&*fp.pat)))
                              .collect::<Vec<String>>().join(", "),
                 if etc { ", ..." } else { "" }
             )
@@ -2578,34 +2566,36 @@ fn name_from_pat(p: &hir::Pat) -> String {
 fn resolve_type(cx: &DocContext,
                 path: Path,
                 id: ast::NodeId) -> Type {
+    debug!("resolve_type({:?},{:?})", path, id);
     let tcx = match cx.tcx_opt() {
         Some(tcx) => tcx,
         // If we're extracting tests, this return value doesn't matter.
         None => return Primitive(Bool),
     };
-    debug!("searching for {} in defmap", id);
     let def = match tcx.def_map.borrow().get(&id) {
         Some(k) => k.full_def(),
         None => panic!("unresolved id not in defmap")
     };
 
+    debug!("resolve_type: def={:?}", def);
+
     let is_generic = match def {
         def::DefPrimTy(p) => match p {
             hir::TyStr => return Primitive(Str),
             hir::TyBool => return Primitive(Bool),
             hir::TyChar => return Primitive(Char),
-            hir::TyInt(hir::TyIs) => return Primitive(Isize),
-            hir::TyInt(hir::TyI8) => return Primitive(I8),
-            hir::TyInt(hir::TyI16) => return Primitive(I16),
-            hir::TyInt(hir::TyI32) => return Primitive(I32),
-            hir::TyInt(hir::TyI64) => return Primitive(I64),
-            hir::TyUint(hir::TyUs) => return Primitive(Usize),
-            hir::TyUint(hir::TyU8) => return Primitive(U8),
-            hir::TyUint(hir::TyU16) => return Primitive(U16),
-            hir::TyUint(hir::TyU32) => return Primitive(U32),
-            hir::TyUint(hir::TyU64) => return Primitive(U64),
-            hir::TyFloat(hir::TyF32) => return Primitive(F32),
-            hir::TyFloat(hir::TyF64) => return Primitive(F64),
+            hir::TyInt(ast::TyIs) => return Primitive(Isize),
+            hir::TyInt(ast::TyI8) => return Primitive(I8),
+            hir::TyInt(ast::TyI16) => return Primitive(I16),
+            hir::TyInt(ast::TyI32) => return Primitive(I32),
+            hir::TyInt(ast::TyI64) => return Primitive(I64),
+            hir::TyUint(ast::TyUs) => return Primitive(Usize),
+            hir::TyUint(ast::TyU8) => return Primitive(U8),
+            hir::TyUint(ast::TyU16) => return Primitive(U16),
+            hir::TyUint(ast::TyU32) => return Primitive(U32),
+            hir::TyUint(ast::TyU64) => return Primitive(U64),
+            hir::TyFloat(ast::TyF32) => return Primitive(F32),
+            hir::TyFloat(ast::TyF64) => return Primitive(F64),
         },
         def::DefSelfTy(..) if path.segments.len() == 1 => {
             return Generic(special_idents::type_self.name.to_string());
@@ -2618,6 +2608,8 @@ fn resolve_type(cx: &DocContext,
 }
 
 fn register_def(cx: &DocContext, def: def::Def) -> DefId {
+    debug!("register_def({:?})", def);
+
     let (did, kind) = match def {
         def::DefFn(i, _) => (i, TypeFunction),
         def::DefTy(i, false) => (i, TypeTypedef),
@@ -2627,6 +2619,8 @@ fn register_def(cx: &DocContext, def: def::Def) -> DefId {
         def::DefMod(i) => (i, TypeModule),
         def::DefStatic(i, _) => (i, TypeStatic),
         def::DefVariant(i, _, _) => (i, TypeEnum),
+        def::DefSelfTy(Some(def_id), _) => (def_id, TypeTrait),
+        def::DefSelfTy(_, Some((impl_id, _))) => return cx.map.local_def_id(impl_id),
         _ => return def.def_id()
     };
     if did.is_local() { return did }
@@ -2669,7 +2663,7 @@ impl Clean<Item> for doctree::Macro {
             source: self.whence.clean(cx),
             visibility: hir::Public.clean(cx),
             stability: self.stab.clean(cx),
-            def_id: DefId::local(self.id),
+            def_id: cx.map.local_def_id(self.id),
             inner: MacroItem(Macro {
                 source: self.whence.to_src(cx),
                 imported_from: self.imported_from.clean(cx),
@@ -2680,7 +2674,7 @@ impl Clean<Item> for doctree::Macro {
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Stability {
-    pub level: attr::StabilityLevel,
+    pub level: stability::StabilityLevel,
     pub feature: String,
     pub since: String,
     pub deprecated_since: String,
@@ -2691,32 +2685,36 @@ pub struct Stability {
 impl Clean<Stability> for attr::Stability {
     fn clean(&self, _: &DocContext) -> Stability {
         Stability {
-            level: self.level,
+            level: stability::StabilityLevel::from_attr_level(&self.level),
             feature: self.feature.to_string(),
-            since: self.since.as_ref().map_or("".to_string(),
-                                              |interned| interned.to_string()),
-            deprecated_since: self.deprecated_since.as_ref().map_or("".to_string(),
-                                                                    |istr| istr.to_string()),
-            reason: self.reason.as_ref().map_or("".to_string(),
-                                                |interned| interned.to_string()),
-            issue: self.issue,
+            since: match self.level {
+                attr::Stable {ref since} => since.to_string(),
+                _ => "".to_string(),
+            },
+            deprecated_since: match self.depr {
+                Some(attr::Deprecation {ref since, ..}) => since.to_string(),
+                _=> "".to_string(),
+            },
+            reason: {
+                if let Some(ref depr) = self.depr {
+                    depr.reason.to_string()
+                } else if let attr::Unstable {reason: Some(ref reason), ..} = self.level {
+                    reason.to_string()
+                } else {
+                    "".to_string()
+                }
+            },
+            issue: match self.level {
+                attr::Unstable {issue, ..} => Some(issue),
+                _ => None,
+            }
         }
     }
 }
 
 impl<'a> Clean<Stability> for &'a attr::Stability {
-    fn clean(&self, _: &DocContext) -> Stability {
-        Stability {
-            level: self.level,
-            feature: self.feature.to_string(),
-            since: self.since.as_ref().map_or("".to_string(),
-                                              |interned| interned.to_string()),
-            deprecated_since: self.deprecated_since.as_ref().map_or("".to_string(),
-                                                                    |istr| istr.to_string()),
-            reason: self.reason.as_ref().map_or("".to_string(),
-                                                |interned| interned.to_string()),
-            issue: self.issue,
-        }
+    fn clean(&self, dc: &DocContext) -> Stability {
+        (**self).clean(dc)
     }
 }
 
@@ -2842,7 +2840,7 @@ pub struct TypeBinding {
 impl Clean<TypeBinding> for hir::TypeBinding {
     fn clean(&self, cx: &DocContext) -> TypeBinding {
         TypeBinding {
-            name: self.ident.clean(cx),
+            name: self.name.clean(cx),
             ty: self.ty.clean(cx)
         }
     }
index 63468dd55f8a900e5d06d0bd7ab5fbdfcd387bea..4955951d36e84afe7711445c5374d161cd9a439f 100644 (file)
@@ -13,13 +13,13 @@ use rustc_lint;
 use rustc_driver::{driver, target_features};
 use rustc::session::{self, config};
 use rustc::middle::def_id::DefId;
-use rustc::middle::{privacy, ty};
+use rustc::middle::ty;
 use rustc::front::map as hir_map;
 use rustc::lint;
+use rustc::util::nodemap::DefIdSet;
 use rustc_trans::back::link;
 use rustc_resolve as resolve;
-use rustc_front::lowering::lower_crate;
-use rustc_front::hir;
+use rustc_front::lowering::{lower_crate, LoweringContext};
 
 use syntax::{ast, codemap, diagnostic};
 use syntax::feature_gate::UnstableFeatures;
@@ -37,14 +37,14 @@ pub use rustc::session::search_paths::SearchPaths;
 /// Are we generating documentation (`Typed`) or tests (`NotTyped`)?
 pub enum MaybeTyped<'a, 'tcx: 'a> {
     Typed(&'a ty::ctxt<'tcx>),
-    NotTyped(session::Session)
+    NotTyped(&'a session::Session)
 }
 
 pub type ExternalPaths = RefCell<Option<HashMap<DefId,
                                                 (Vec<String>, clean::TypeKind)>>>;
 
 pub struct DocContext<'a, 'tcx: 'a> {
-    pub krate: &'tcx hir::Crate,
+    pub map: &'a hir_map::Map<'tcx>,
     pub maybe_typed: MaybeTyped<'a, 'tcx>,
     pub input: Input,
     pub external_paths: ExternalPaths,
@@ -77,8 +77,8 @@ impl<'b, 'tcx> DocContext<'b, 'tcx> {
 }
 
 pub struct CrateAnalysis {
-    pub exported_items: privacy::ExportedItems,
-    pub public_items: privacy::PublicItems,
+    pub exported_items: DefIdSet,
+    pub public_items: DefIdSet,
     pub external_paths: ExternalPaths,
     pub external_typarams: RefCell<Option<HashMap<DefId, String>>>,
     pub inlined: RefCell<Option<HashSet<DefId>>>,
@@ -135,21 +135,32 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
 
     let krate = driver::assign_node_ids(&sess, krate);
     // Lower ast -> hir.
-    let mut hir_forest = hir_map::Forest::new(lower_crate(&krate));
+    let lcx = LoweringContext::new(&sess, Some(&krate));
+    let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate));
     let arenas = ty::CtxtArenas::new();
     let hir_map = driver::make_map(&sess, &mut hir_forest);
 
-    driver::phase_3_run_analysis_passes(sess,
+    driver::phase_3_run_analysis_passes(&sess,
                                         hir_map,
-                                        &krate,
                                         &arenas,
-                                        name,
+                                        &name,
                                         resolve::MakeGlobMap::No,
                                         |tcx, analysis| {
         let ty::CrateAnalysis { exported_items, public_items, .. } = analysis;
 
+        // Convert from a NodeId set to a DefId set since we don't always have easy access
+        // to the map from defid -> nodeid
+        let exported_items: DefIdSet =
+            exported_items.into_iter()
+                          .map(|n| tcx.map.local_def_id(n))
+                          .collect();
+        let public_items: DefIdSet =
+            public_items.into_iter()
+                        .map(|n| tcx.map.local_def_id(n))
+                        .collect();
+
         let ctxt = DocContext {
-            krate: tcx.map.krate(),
+            map: &tcx.map,
             maybe_typed: Typed(tcx),
             input: input,
             external_traits: RefCell::new(Some(HashMap::new())),
@@ -159,7 +170,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
             populated_crate_impls: RefCell::new(HashSet::new()),
             deref_trait_did: Cell::new(None),
         };
-        debug!("crate: {:?}", ctxt.krate);
+        debug!("crate: {:?}", ctxt.map.krate());
 
         let mut analysis = CrateAnalysis {
             exported_items: exported_items,
@@ -172,7 +183,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
 
         let krate = {
             let mut v = RustdocVisitor::new(&ctxt, Some(&analysis));
-            v.visit(ctxt.krate);
+            v.visit(ctxt.map.krate());
             v.clean(&ctxt)
         };
 
@@ -184,5 +195,5 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
         *analysis.inlined.borrow_mut() = map;
         analysis.deref_trait_did = ctxt.deref_trait_did.get();
         (krate, analysis)
-    }).1
+    })
 }
index 5140cca03ea340eb1ffc0c0301330f7682f57dff..9550109fe9ff8279558b067ddcd4650f10c8927a 100644 (file)
@@ -17,14 +17,14 @@ use syntax;
 use syntax::codemap::Span;
 use syntax::abi;
 use syntax::ast;
-use syntax::ast::{Ident, NodeId};
+use syntax::ast::{Name, NodeId};
+use syntax::attr;
 use syntax::ptr::P;
 use rustc_front::hir;
-use rustc_front::attr;
 
 pub struct Module {
-    pub name: Option<Ident>,
-    pub attrs: Vec<hir::Attribute>,
+    pub name: Option<Name>,
+    pub attrs: Vec<ast::Attribute>,
     pub where_outer: Span,
     pub where_inner: Span,
     pub extern_crates: Vec<ExternCrate>,
@@ -48,7 +48,7 @@ pub struct Module {
 }
 
 impl Module {
-    pub fn new(name: Option<Ident>) -> Module {
+    pub fn new(name: Option<Name>) -> Module {
         Module {
             name       : name,
             id: 0,
@@ -98,9 +98,9 @@ pub struct Struct {
     pub stab: Option<attr::Stability>,
     pub id: NodeId,
     pub struct_type: StructType,
-    pub name: Ident,
+    pub name: Name,
     pub generics: hir::Generics,
-    pub attrs: Vec<hir::Attribute>,
+    pub attrs: Vec<ast::Attribute>,
     pub fields: Vec<hir::StructField>,
     pub whence: Span,
 }
@@ -110,27 +110,25 @@ pub struct Enum {
     pub stab: Option<attr::Stability>,
     pub variants: Vec<Variant>,
     pub generics: hir::Generics,
-    pub attrs: Vec<hir::Attribute>,
+    pub attrs: Vec<ast::Attribute>,
     pub id: NodeId,
     pub whence: Span,
-    pub name: Ident,
+    pub name: Name,
 }
 
 pub struct Variant {
-    pub name: Ident,
-    pub attrs: Vec<hir::Attribute>,
-    pub kind: hir::VariantKind,
-    pub id: ast::NodeId,
-    pub vis: hir::Visibility,
+    pub name: Name,
+    pub attrs: Vec<ast::Attribute>,
+    pub def: hir::VariantData,
     pub stab: Option<attr::Stability>,
     pub whence: Span,
 }
 
 pub struct Function {
     pub decl: hir::FnDecl,
-    pub attrs: Vec<hir::Attribute>,
+    pub attrs: Vec<ast::Attribute>,
     pub id: NodeId,
-    pub name: Ident,
+    pub name: Name,
     pub vis: hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub unsafety: hir::Unsafety,
@@ -143,9 +141,9 @@ pub struct Function {
 pub struct Typedef {
     pub ty: P<hir::Ty>,
     pub gen: hir::Generics,
-    pub name: Ident,
+    pub name: Name,
     pub id: ast::NodeId,
-    pub attrs: Vec<hir::Attribute>,
+    pub attrs: Vec<ast::Attribute>,
     pub whence: Span,
     pub vis: hir::Visibility,
     pub stab: Option<attr::Stability>,
@@ -156,8 +154,8 @@ pub struct Static {
     pub type_: P<hir::Ty>,
     pub mutability: hir::Mutability,
     pub expr: P<hir::Expr>,
-    pub name: Ident,
-    pub attrs: Vec<hir::Attribute>,
+    pub name: Name,
+    pub attrs: Vec<ast::Attribute>,
     pub vis: hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub id: ast::NodeId,
@@ -167,8 +165,8 @@ pub struct Static {
 pub struct Constant {
     pub type_: P<hir::Ty>,
     pub expr: P<hir::Expr>,
-    pub name: Ident,
-    pub attrs: Vec<hir::Attribute>,
+    pub name: Name,
+    pub attrs: Vec<ast::Attribute>,
     pub vis: hir::Visibility,
     pub stab: Option<attr::Stability>,
     pub id: ast::NodeId,
@@ -177,11 +175,11 @@ pub struct Constant {
 
 pub struct Trait {
     pub unsafety: hir::Unsafety,
-    pub name: Ident,
+    pub name: Name,
     pub items: Vec<P<hir::TraitItem>>, //should be TraitItem
     pub generics: hir::Generics,
     pub bounds: Vec<hir::TyParamBound>,
-    pub attrs: Vec<hir::Attribute>,
+    pub attrs: Vec<ast::Attribute>,
     pub id: ast::NodeId,
     pub whence: Span,
     pub vis: hir::Visibility,
@@ -195,7 +193,7 @@ pub struct Impl {
     pub trait_: Option<hir::TraitRef>,
     pub for_: P<hir::Ty>,
     pub items: Vec<P<hir::ImplItem>>,
-    pub attrs: Vec<hir::Attribute>,
+    pub attrs: Vec<ast::Attribute>,
     pub whence: Span,
     pub vis: hir::Visibility,
     pub stab: Option<attr::Stability>,
@@ -206,39 +204,39 @@ pub struct DefaultImpl {
     pub unsafety: hir::Unsafety,
     pub trait_: hir::TraitRef,
     pub id: ast::NodeId,
-    pub attrs: Vec<hir::Attribute>,
+    pub attrs: Vec<ast::Attribute>,
     pub whence: Span,
 }
 
 pub struct Macro {
-    pub name: Ident,
+    pub name: Name,
     pub id: ast::NodeId,
-    pub attrs: Vec<hir::Attribute>,
+    pub attrs: Vec<ast::Attribute>,
     pub whence: Span,
     pub stab: Option<attr::Stability>,
-    pub imported_from: Option<Ident>,
+    pub imported_from: Option<Name>,
 }
 
 pub struct ExternCrate {
-    pub name: Ident,
+    pub name: Name,
     pub path: Option<String>,
     pub vis: hir::Visibility,
-    pub attrs: Vec<hir::Attribute>,
+    pub attrs: Vec<ast::Attribute>,
     pub whence: Span,
 }
 
 pub struct Import {
     pub id: NodeId,
     pub vis: hir::Visibility,
-    pub attrs: Vec<hir::Attribute>,
+    pub attrs: Vec<ast::Attribute>,
     pub node: hir::ViewPath_,
     pub whence: Span,
 }
 
-pub fn struct_type_from_def(sd: &hir::StructDef) -> StructType {
-    if sd.ctor_id.is_some() {
+pub fn struct_type_from_def(sd: &hir::VariantData) -> StructType {
+    if !sd.is_struct() {
         // We are in a tuple-struct
-        match sd.fields.len() {
+        match sd.fields().len() {
             0 => Unit,
             1 => Newtype,
             _ => Tuple
index 947ae3abd8d776a39ea55167a59d9c162bf2b1d2..d12c5d2c6fb6b3a5350997c12cd385b7c3e9b5ac 100644 (file)
@@ -18,9 +18,9 @@
 use std::fmt;
 use std::iter::repeat;
 
-use rustc::middle::def_id::{DefId, LOCAL_CRATE};
+use rustc::metadata::cstore::LOCAL_CRATE;
+use rustc::middle::def_id::{CRATE_DEF_INDEX, DefId};
 use syntax::abi::Abi;
-use syntax::ast;
 use rustc_front::hir;
 
 use clean;
@@ -386,7 +386,7 @@ fn primitive_link(f: &mut fmt::Formatter,
         Some(&cnum) => {
             let path = &m.paths[&DefId {
                 krate: cnum,
-                node: ast::CRATE_NODE_ID,
+                index: CRATE_DEF_INDEX,
             }];
             let loc = match m.extern_locations[&cnum] {
                 (_, render::Remote(ref s)) => Some(s.to_string()),
index c98a54e451475f1da6280182f0288270a7b55dd0..f68e82501e91ea4d9123b85d25933553edf4da86 100644 (file)
@@ -207,9 +207,7 @@ fn stripped_filtered_line<'a>(s: &'a str) -> Option<&'a str> {
 ///
 /// Any leading or trailing whitespace will be trimmed.
 fn collapse_whitespace(s: &str) -> String {
-    s.split(|c: char| c.is_whitespace()).filter(|s| {
-        !s.is_empty()
-    }).collect::<Vec<_>>().join(" ")
+    s.split_whitespace().collect::<Vec<_>>().join(" ")
 }
 
 thread_local!(static USED_HEADER_MAP: RefCell<HashMap<String, usize>> = {
@@ -277,25 +275,44 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
 
         // Extract the text provided
         let s = if text.is_null() {
-            "".to_string()
+            "".to_owned()
         } else {
             let s = unsafe { (*text).as_bytes() };
-            str::from_utf8(s).unwrap().to_string()
+            str::from_utf8(&s).unwrap().to_owned()
         };
 
-        // Transform the contents of the header into a hyphenated string
-        let id = s.split_whitespace().map(|s| s.to_ascii_lowercase())
-            .collect::<Vec<String>>().join("-");
-
+        // Discard '<em>', '<code>' tags and some escaped characters,
+        // transform the contents of the header into a hyphenated string
+        // without non-alphanumeric characters other than '-' and '_'.
+        //
         // This is a terrible hack working around how hoedown gives us rendered
         // html for text rather than the raw text.
+        let mut id = s.clone();
+        let repl_sub = vec!["<em>", "</em>", "<code>", "</code>",
+                            "<strong>", "</strong>",
+                            "&lt;", "&gt;", "&amp;", "&#39;", "&quot;"];
+        for sub in repl_sub {
+            id = id.replace(sub, "");
+        }
+        let id = id.chars().filter_map(|c| {
+            if c.is_alphanumeric() || c == '-' || c == '_' {
+                if c.is_ascii() {
+                    Some(c.to_ascii_lowercase())
+                } else {
+                    Some(c)
+                }
+            } else if c.is_whitespace() && c.is_ascii() {
+                Some('-')
+            } else {
+                None
+            }
+        }).collect::<String>();
 
         let opaque = unsafe { (*data).opaque as *mut hoedown_html_renderer_state };
         let opaque = unsafe { &mut *((*opaque).opaque as *mut MyOpaque) };
 
         // Make sure our hyphenated ID is unique for this page
         let id = USED_HEADER_MAP.with(|map| {
-            let id = id.replace("<code>", "").replace("</code>", "").to_string();
             let id = match map.borrow_mut().get_mut(&id) {
                 None => id,
                 Some(a) => { *a += 1; format!("{}-{}", id, *a - 1) }
@@ -304,22 +321,15 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
             id
         });
 
-        let sec = match opaque.toc_builder {
-            Some(ref mut builder) => {
-                builder.push(level as u32, s.clone(), id.clone())
-            }
-            None => {""}
-        };
+
+        let sec = opaque.toc_builder.as_mut().map_or("".to_owned(), |builder| {
+            format!("{} ", builder.push(level as u32, s.clone(), id.clone()))
+        });
 
         // Render the HTML
-        let text = format!(r##"<h{lvl} id="{id}" class='section-header'><a
-                           href="#{id}">{sec}{}</a></h{lvl}>"##,
-                           s, lvl = level, id = id,
-                           sec = if sec.is_empty() {
-                               sec.to_string()
-                           } else {
-                               format!("{} ", sec)
-                           });
+        let text = format!("<h{lvl} id='{id}' class='section-header'>\
+                           <a href='#{id}'>{sec}{}</a></h{lvl}>",
+                           s, lvl = level, id = id, sec = sec);
 
         let text = CString::new(text).unwrap();
         unsafe { hoedown_buffer_puts(ob, text.as_ptr()) }
@@ -333,7 +343,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
         _: *const hoedown_renderer_data,
     ) -> libc::c_int {
         let content = if text.is_null() {
-            "".to_string()
+            "".to_owned()
         } else {
             let bytes = unsafe { (*text).as_bytes() };
             let s = str::from_utf8(bytes).unwrap();
@@ -367,10 +377,9 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
 
         hoedown_html_renderer_free(renderer);
 
-        let mut ret = match opaque.toc_builder {
-            Some(b) => write!(w, "<nav id=\"TOC\">{}</nav>", b.into_toc()),
-            None => Ok(())
-        };
+        let mut ret = opaque.toc_builder.map_or(Ok(()), |builder| {
+            write!(w, "<nav id=\"TOC\">{}</nav>", builder.into_toc())
+        });
 
         if ret.is_ok() {
             let buf = (*ob).as_bytes();
@@ -404,7 +413,7 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) {
                 stripped_filtered_line(l).unwrap_or(l)
             });
             let text = lines.collect::<Vec<&str>>().join("\n");
-            tests.add_test(text.to_string(),
+            tests.add_test(text.to_owned(),
                            block_info.should_panic, block_info.no_run,
                            block_info.ignore, block_info.test_harness);
         }
@@ -560,10 +569,7 @@ pub fn plain_summary_line(md: &str) -> String {
                                 md.len() as libc::size_t);
         hoedown_document_free(document);
         let plain_slice = (*ob).as_bytes();
-        let plain = match str::from_utf8(plain_slice) {
-            Ok(s) => s.to_string(),
-            Err(_) => "".to_string(),
-        };
+        let plain = str::from_utf8(plain_slice).unwrap_or("").to_owned();
         hoedown_buffer_free(ob);
         plain
     }
@@ -572,7 +578,7 @@ pub fn plain_summary_line(md: &str) -> String {
 #[cfg(test)]
 mod tests {
     use super::{LangString, Markdown};
-    use super::{collapse_whitespace, plain_summary_line};
+    use super::plain_summary_line;
 
     #[test]
     fn test_lang_string_parse() {
@@ -607,6 +613,27 @@ mod tests {
         format!("{}", Markdown(markdown));
     }
 
+    #[test]
+    fn test_header() {
+        fn t(input: &str, expect: &str) {
+            let output = format!("{}", Markdown(input));
+            assert_eq!(output, expect);
+        }
+
+        t("# Foo bar", "\n<h1 id='foo-bar' class='section-header'>\
+          <a href='#foo-bar'>Foo bar</a></h1>");
+        t("## Foo-bar_baz qux", "\n<h2 id='foo-bar_baz-qux' class=\'section-\
+          header'><a href='#foo-bar_baz-qux'>Foo-bar_baz qux</a></h2>");
+        t("### **Foo** *bar* baz!?!& -_qux_-%",
+          "\n<h3 id='foo-bar-baz--_qux_-' class='section-header'>\
+          <a href='#foo-bar-baz--_qux_-'><strong>Foo</strong> \
+          <em>bar</em> baz!?!&amp; -_qux_-%</a></h3>");
+        t("####**Foo?** & \\*bar?!*  _`baz`_ ❤ #qux",
+          "\n<h4 id='foo--bar--baz--qux' class='section-header'>\
+          <a href='#foo--bar--baz--qux'><strong>Foo?</strong> &amp; *bar?!*  \
+          <em><code>baz</code></em> ❤ #qux</a></h4>");
+    }
+
     #[test]
     fn test_plain_summary_line() {
         fn t(input: &str, expect: &str) {
@@ -620,18 +647,4 @@ mod tests {
         t("# top header", "top header");
         t("## header", "header");
     }
-
-    #[test]
-    fn test_collapse_whitespace() {
-        fn t(input: &str, expected: &str) {
-            let actual = collapse_whitespace(input);
-            assert_eq!(actual, expected);
-        }
-
-        t("foo", "foo");
-        t("foo bar baz", "foo bar baz");
-        t(" foo   bar", "foo bar");
-        t("\tfoo   bar\nbaz", "foo bar baz");
-        t("foo   bar \n   baz\t\tqux\n", "foo bar baz qux");
-    }
 }
index 86b268001a6aeb357e682abac729a6492b7ab370..49228ac91f6b9082d0d6934e3cf2b0a7be1d1566 100644 (file)
@@ -39,7 +39,8 @@ use std::cell::RefCell;
 use std::cmp::Ordering;
 use std::collections::{BTreeMap, HashMap, HashSet};
 use std::default::Default;
-use std::fmt;
+use std::error;
+use std::fmt::{self, Display, Formatter};
 use std::fs::{self, File};
 use std::io::prelude::*;
 use std::io::{self, BufWriter, BufReader};
@@ -53,9 +54,11 @@ use externalfiles::ExternalHtml;
 
 use serialize::json::{self, ToJson};
 use syntax::{abi, ast};
-use rustc::middle::def_id::{DefId, LOCAL_CRATE};
-use rustc::util::nodemap::NodeSet;
-use rustc_front::{hir, attr};
+use rustc::metadata::cstore::LOCAL_CRATE;
+use rustc::middle::def_id::{CRATE_DEF_INDEX, DefId};
+use rustc::middle::stability;
+use rustc::util::nodemap::DefIdSet;
+use rustc_front::hir;
 
 use clean::{self, SelfTy};
 use doctree;
@@ -143,6 +146,42 @@ impl Impl {
     }
 }
 
+#[derive(Debug)]
+pub struct Error {
+    file: PathBuf,
+    error: io::Error,
+}
+
+impl error::Error for Error {
+    fn description(&self) -> &str {
+        self.error.description()
+    }
+}
+
+impl Display for Error {
+    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+        write!(f, "\"{}\": {}", self.file.display(), self.error)
+    }
+}
+
+impl Error {
+    pub fn new(e: io::Error, file: &Path) -> Error {
+        Error {
+            file: file.to_path_buf(),
+            error: e,
+        }
+    }
+}
+
+macro_rules! try_err {
+    ($e:expr, $file:expr) => ({
+        match $e {
+            Ok(e) => e,
+            Err(e) => return Err(Error::new(e, $file)),
+        }
+    })
+}
+
 /// This cache is used to store information about the `clean::Crate` being
 /// rendered in order to provide more useful documentation. This contains
 /// information like all implementors of a trait, all traits a type implements,
@@ -205,7 +244,7 @@ pub struct Cache {
     search_index: Vec<IndexItem>,
     privmod: bool,
     remove_priv: bool,
-    public_items: NodeSet,
+    public_items: DefIdSet,
     deref_trait_did: Option<DefId>,
 
     // In rare case where a structure is defined in one module but implemented
@@ -213,7 +252,7 @@ pub struct Cache {
     // then the fully qualified name of the structure isn't presented in `paths`
     // yet when its implementation methods are being indexed. Caches such methods
     // and their parent id here and indexes them at the end of crate parsing.
-    orphan_methods: Vec<(ast::NodeId, clean::Item)>,
+    orphan_methods: Vec<(DefId, clean::Item)>,
 }
 
 /// Helper struct to render all source code to HTML pages
@@ -308,7 +347,7 @@ thread_local!(pub static CURRENT_LOCATION_KEY: RefCell<Vec<String>> =
 pub fn run(mut krate: clean::Crate,
            external_html: &ExternalHtml,
            dst: PathBuf,
-           passes: HashSet<String>) -> io::Result<()> {
+           passes: HashSet<String>) -> Result<(), Error> {
     let src_root = match krate.src.parent() {
         Some(p) => p.to_path_buf(),
         None => PathBuf::new(),
@@ -331,7 +370,7 @@ pub fn run(mut krate: clean::Crate,
         issue_tracker_base_url: None,
     };
 
-    try!(mkdir(&cx.dst));
+    try_err!(mkdir(&cx.dst), &cx.dst);
 
     // Crawl the crate attributes looking for attributes which control how we're
     // going to emit HTML
@@ -377,7 +416,7 @@ pub fn run(mut krate: clean::Crate,
     let analysis = ::ANALYSISKEY.with(|a| a.clone());
     let analysis = analysis.borrow();
     let public_items = analysis.as_ref().map(|a| a.public_items.clone());
-    let public_items = public_items.unwrap_or(NodeSet());
+    let public_items = public_items.unwrap_or(DefIdSet());
     let paths: HashMap<DefId, (Vec<String>, ItemType)> =
       analysis.as_ref().map(|a| {
         let paths = a.external_paths.borrow_mut().take().unwrap();
@@ -412,7 +451,7 @@ pub fn run(mut krate: clean::Crate,
     for &(n, ref e) in &krate.externs {
         cache.extern_locations.insert(n, (e.name.clone(),
                                           extern_location(e, &cx.dst)));
-        let did = DefId { krate: n, node: ast::CRATE_NODE_ID };
+        let did = DefId { krate: n, index: CRATE_DEF_INDEX };
         cache.paths.insert(did, (vec![e.name.to_string()], ItemType::Module));
     }
 
@@ -433,7 +472,7 @@ pub fn run(mut krate: clean::Crate,
     krate = cache.fold_crate(krate);
 
     // Build our search index
-    let index = try!(build_index(&krate, &mut cache));
+    let index = build_index(&krate, &mut cache);
 
     // Freeze the cache now that the index has been built. Put an Arc into TLS
     // for future parallelization opportunities
@@ -448,7 +487,7 @@ pub fn run(mut krate: clean::Crate,
     cx.krate(krate)
 }
 
-fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
+fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String {
     // Build the search index from the collected metadata
     let mut nodeid_to_pathid = HashMap::new();
     let mut pathid_to_nodeid = Vec::new();
@@ -459,8 +498,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
 
         // Attach all orphan methods to the type's definition if the type
         // has since been learned.
-        for &(pid, ref item) in orphan_methods {
-            let did = DefId::local(pid);
+        for &(did, ref item) in orphan_methods {
             match paths.get(&did) {
                 Some(&(ref fqp, _)) => {
                     // Needed to determine `self` type.
@@ -476,7 +514,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
                 },
                 None => {}
             }
-        };
+        }
 
         // Reduce `NodeId` in paths into smaller sequential numbers,
         // and prune the paths that do not appear in the index.
@@ -497,7 +535,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
 
     // Collect the index into a string
     let mut w = io::Cursor::new(Vec::new());
-    try!(write!(&mut w, r#"searchIndex['{}'] = {{"items":["#, krate.name));
+    write!(&mut w, r#"searchIndex['{}'] = {{"items":["#, krate.name).unwrap();
 
     let mut lastpath = "".to_string();
     for (i, item) in cache.search_index.iter().enumerate() {
@@ -511,74 +549,91 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> io::Result<String> {
         };
 
         if i > 0 {
-            try!(write!(&mut w, ","));
+            write!(&mut w, ",").unwrap();
         }
-        try!(write!(&mut w, r#"[{},"{}","{}",{}"#,
-                    item.ty as usize, item.name, path,
-                    item.desc.to_json().to_string()));
+        write!(&mut w, r#"[{},"{}","{}",{}"#,
+               item.ty as usize, item.name, path,
+               item.desc.to_json().to_string()).unwrap();
         match item.parent {
             Some(nodeid) => {
                 let pathid = *nodeid_to_pathid.get(&nodeid).unwrap();
-                try!(write!(&mut w, ",{}", pathid));
+                write!(&mut w, ",{}", pathid).unwrap();
             }
-            None => try!(write!(&mut w, ",null"))
+            None => write!(&mut w, ",null").unwrap()
         }
         match item.search_type {
-            Some(ref t) => try!(write!(&mut w, ",{}", t)),
-            None => try!(write!(&mut w, ",null"))
+            Some(ref t) => write!(&mut w, ",{}", t).unwrap(),
+            None => write!(&mut w, ",null").unwrap()
         }
-        try!(write!(&mut w, "]"));
+        write!(&mut w, "]").unwrap();
     }
 
-    try!(write!(&mut w, r#"],"paths":["#));
+    write!(&mut w, r#"],"paths":["#).unwrap();
 
     for (i, &did) in pathid_to_nodeid.iter().enumerate() {
         let &(ref fqp, short) = cache.paths.get(&did).unwrap();
         if i > 0 {
-            try!(write!(&mut w, ","));
+            write!(&mut w, ",").unwrap();
         }
-        try!(write!(&mut w, r#"[{},"{}"]"#,
-                    short as usize, *fqp.last().unwrap()));
+        write!(&mut w, r#"[{},"{}"]"#,
+               short as usize, *fqp.last().unwrap()).unwrap();
     }
 
-    try!(write!(&mut w, "]}};"));
+    write!(&mut w, "]}};").unwrap();
 
-    Ok(String::from_utf8(w.into_inner()).unwrap())
+    String::from_utf8(w.into_inner()).unwrap()
 }
 
 fn write_shared(cx: &Context,
                 krate: &clean::Crate,
                 cache: &Cache,
-                search_index: String) -> io::Result<()> {
+                search_index: String) -> Result<(), Error> {
     // Write out the shared files. Note that these are shared among all rustdoc
     // docs placed in the output directory, so this needs to be a synchronized
     // operation with respect to all other rustdocs running around.
-    try!(mkdir(&cx.dst));
+    try_err!(mkdir(&cx.dst), &cx.dst);
     let _lock = ::flock::Lock::new(&cx.dst.join(".lock"));
 
     // Add all the static files. These may already exist, but we just
     // overwrite them anyway to make sure that they're fresh and up-to-date.
     try!(write(cx.dst.join("jquery.js"),
                include_bytes!("static/jquery-2.1.4.min.js")));
-    try!(write(cx.dst.join("main.js"), include_bytes!("static/main.js")));
-    try!(write(cx.dst.join("playpen.js"), include_bytes!("static/playpen.js")));
-    try!(write(cx.dst.join("main.css"), include_bytes!("static/main.css")));
+    try!(write(cx.dst.join("main.js"),
+               include_bytes!("static/main.js")));
+    try!(write(cx.dst.join("playpen.js"),
+               include_bytes!("static/playpen.js")));
+    try!(write(cx.dst.join("main.css"),
+               include_bytes!("static/main.css")));
     try!(write(cx.dst.join("normalize.css"),
                include_bytes!("static/normalize.css")));
     try!(write(cx.dst.join("FiraSans-Regular.woff"),
                include_bytes!("static/FiraSans-Regular.woff")));
     try!(write(cx.dst.join("FiraSans-Medium.woff"),
                include_bytes!("static/FiraSans-Medium.woff")));
+    try!(write(cx.dst.join("FiraSans-LICENSE.txt"),
+               include_bytes!("static/FiraSans-LICENSE.txt")));
     try!(write(cx.dst.join("Heuristica-Italic.woff"),
                include_bytes!("static/Heuristica-Italic.woff")));
+    try!(write(cx.dst.join("Heuristica-LICENSE.txt"),
+               include_bytes!("static/Heuristica-LICENSE.txt")));
     try!(write(cx.dst.join("SourceSerifPro-Regular.woff"),
                include_bytes!("static/SourceSerifPro-Regular.woff")));
     try!(write(cx.dst.join("SourceSerifPro-Bold.woff"),
                include_bytes!("static/SourceSerifPro-Bold.woff")));
+    try!(write(cx.dst.join("SourceSerifPro-LICENSE.txt"),
+               include_bytes!("static/SourceSerifPro-LICENSE.txt")));
     try!(write(cx.dst.join("SourceCodePro-Regular.woff"),
                include_bytes!("static/SourceCodePro-Regular.woff")));
     try!(write(cx.dst.join("SourceCodePro-Semibold.woff"),
                include_bytes!("static/SourceCodePro-Semibold.woff")));
+    try!(write(cx.dst.join("SourceCodePro-LICENSE.txt"),
+               include_bytes!("static/SourceCodePro-LICENSE.txt")));
+    try!(write(cx.dst.join("LICENSE-MIT.txt"),
+               include_bytes!("static/LICENSE-MIT.txt")));
+    try!(write(cx.dst.join("LICENSE-APACHE.txt"),
+               include_bytes!("static/LICENSE-APACHE.txt")));
+    try!(write(cx.dst.join("COPYRIGHT.txt"),
+               include_bytes!("static/COPYRIGHT.txt")));
 
     fn collect(path: &Path, krate: &str,
                key: &str) -> io::Result<Vec<String>> {
@@ -600,18 +655,18 @@ fn write_shared(cx: &Context,
 
     // Update the search index
     let dst = cx.dst.join("search-index.js");
-    let all_indexes = try!(collect(&dst, &krate.name, "searchIndex"));
-    let mut w = try!(File::create(&dst));
-    try!(writeln!(&mut w, "var searchIndex = {{}};"));
-    try!(writeln!(&mut w, "{}", search_index));
+    let all_indexes = try_err!(collect(&dst, &krate.name, "searchIndex"), &dst);
+    let mut w = try_err!(File::create(&dst), &dst);
+    try_err!(writeln!(&mut w, "var searchIndex = {{}};"), &dst);
+    try_err!(writeln!(&mut w, "{}", search_index), &dst);
     for index in &all_indexes {
-        try!(writeln!(&mut w, "{}", *index));
+        try_err!(writeln!(&mut w, "{}", *index), &dst);
     }
-    try!(writeln!(&mut w, "initSearch(searchIndex);"));
+    try_err!(writeln!(&mut w, "initSearch(searchIndex);"), &dst);
 
     // Update the list of all implementors for traits
     let dst = cx.dst.join("implementors");
-    try!(mkdir(&dst));
+    try_err!(mkdir(&dst), &dst);
     for (&did, imps) in &cache.implementors {
         // Private modules can leak through to this phase of rustdoc, which
         // could contain implementations for otherwise private types. In some
@@ -628,51 +683,53 @@ fn write_shared(cx: &Context,
         let mut mydst = dst.clone();
         for part in &remote_path[..remote_path.len() - 1] {
             mydst.push(part);
-            try!(mkdir(&mydst));
+            try_err!(mkdir(&mydst), &mydst);
         }
         mydst.push(&format!("{}.{}.js",
                             remote_item_type.to_static_str(),
                             remote_path[remote_path.len() - 1]));
-        let all_implementors = try!(collect(&mydst, &krate.name,
-                                            "implementors"));
+        let all_implementors = try_err!(collect(&mydst, &krate.name,
+                                                "implementors"),
+                                        &mydst);
 
-        try!(mkdir(mydst.parent().unwrap()));
-        let mut f = BufWriter::new(try!(File::create(&mydst)));
-        try!(writeln!(&mut f, "(function() {{var implementors = {{}};"));
+        try_err!(mkdir(mydst.parent().unwrap()),
+                 &mydst.parent().unwrap().to_path_buf());
+        let mut f = BufWriter::new(try_err!(File::create(&mydst), &mydst));
+        try_err!(writeln!(&mut f, "(function() {{var implementors = {{}};"), &mydst);
 
         for implementor in &all_implementors {
-            try!(write!(&mut f, "{}", *implementor));
+            try_err!(write!(&mut f, "{}", *implementor), &mydst);
         }
 
-        try!(write!(&mut f, r"implementors['{}'] = [", krate.name));
+        try_err!(write!(&mut f, r"implementors['{}'] = [", krate.name), &mydst);
         for imp in imps {
             // If the trait and implementation are in the same crate, then
             // there's no need to emit information about it (there's inlining
             // going on). If they're in different crates then the crate defining
             // the trait will be interested in our implementation.
             if imp.def_id.krate == did.krate { continue }
-            try!(write!(&mut f, r#""{}","#, imp.impl_));
+            try_err!(write!(&mut f, r#""{}","#, imp.impl_), &mydst);
         }
-        try!(writeln!(&mut f, r"];"));
-        try!(writeln!(&mut f, "{}", r"
+        try_err!(writeln!(&mut f, r"];"), &mydst);
+        try_err!(writeln!(&mut f, "{}", r"
             if (window.register_implementors) {
                 window.register_implementors(implementors);
             } else {
                 window.pending_implementors = implementors;
             }
-        "));
-        try!(writeln!(&mut f, r"}})()"));
+        "), &mydst);
+        try_err!(writeln!(&mut f, r"}})()"), &mydst);
     }
     Ok(())
 }
 
 fn render_sources(cx: &mut Context,
-                  krate: clean::Crate) -> io::Result<clean::Crate> {
+                  krate: clean::Crate) -> Result<clean::Crate, Error> {
     info!("emitting source files");
     let dst = cx.dst.join("src");
-    try!(mkdir(&dst));
+    try_err!(mkdir(&dst), &dst);
     let dst = dst.join(&krate.name);
-    try!(mkdir(&dst));
+    try_err!(mkdir(&dst), &dst);
     let mut folder = SourceCollector {
         dst: dst,
         seen: HashSet::new(),
@@ -685,8 +742,8 @@ fn render_sources(cx: &mut Context,
 
 /// Writes the entire contents of a string to a destination, not attempting to
 /// catch any errors.
-fn write(dst: PathBuf, contents: &[u8]) -> io::Result<()> {
-    try!(File::create(&dst)).write_all(contents)
+fn write(dst: PathBuf, contents: &[u8]) -> Result<(), Error> {
+    Ok(try_err!(try_err!(File::create(&dst), &dst).write_all(contents), &dst))
 }
 
 /// Makes a directory on the filesystem, failing the thread if an error occurs and
@@ -835,7 +892,6 @@ impl<'a> SourceCollector<'a> {
         fname.push(".html");
         cur.push(&fname[..]);
         let mut w = BufWriter::new(try!(File::create(&cur)));
-
         let title = format!("{} -- source", cur.file_name().unwrap()
                                                .to_string_lossy());
         let desc = format!("Source to the Rust file `{}`.", filename);
@@ -968,7 +1024,7 @@ impl DocFolder for Cache {
                     if parent.is_local() {
                         // We have a parent, but we don't know where they're
                         // defined yet. Wait for later to index this item.
-                        self.orphan_methods.push((parent.node, item.clone()))
+                        self.orphan_methods.push((parent, item.clone()))
                     }
                 }
                 _ => {}
@@ -994,10 +1050,11 @@ impl DocFolder for Cache {
                 // `public_items` map, so we can skip inserting into the
                 // paths map if there was already an entry present and we're
                 // not a public item.
-                let id = item.def_id.node;
-                if !self.paths.contains_key(&item.def_id) ||
-                   !item.def_id.is_local() ||
-                   self.public_items.contains(&id) {
+                if
+                    !self.paths.contains_key(&item.def_id) ||
+                    !item.def_id.is_local() ||
+                    self.public_items.contains(&item.def_id)
+                {
                     self.paths.insert(item.def_id,
                                       (self.stack.clone(), shortty(&item)));
                 }
@@ -1033,7 +1090,7 @@ impl DocFolder for Cache {
                     ref t => {
                         match t.primitive_type() {
                             Some(prim) => {
-                                let did = DefId::local(prim.to_node_id());
+                                let did = DefId::local(prim.to_def_index());
                                 self.parent_stack.push(did);
                                 true
                             }
@@ -1078,8 +1135,8 @@ impl DocFolder for Cache {
                             ref t => {
                                 t.primitive_type().and_then(|t| {
                                     self.primitive_locations.get(&t).map(|n| {
-                                        let id = t.to_node_id();
-                                        DefId { krate: *n, node: id }
+                                        let id = t.to_def_index();
+                                        DefId { krate: *n, index: id }
                                     })
                                 })
                             }
@@ -1151,7 +1208,7 @@ impl Context {
     ///
     /// This currently isn't parallelized, but it'd be pretty easy to add
     /// parallelization to this function.
-    fn krate(self, mut krate: clean::Crate) -> io::Result<()> {
+    fn krate(self, mut krate: clean::Crate) -> Result<(), Error> {
         let mut item = match krate.module.take() {
             Some(i) => i,
             None => return Ok(())
@@ -1177,7 +1234,7 @@ impl Context {
     /// all sub-items which need to be rendered.
     ///
     /// The rendering driver uses this closure to queue up more work.
-    fn item<F>(&mut self, item: clean::Item, mut f: F) -> io::Result<()> where
+    fn item<F>(&mut self, item: clean::Item, mut f: F) -> Result<(), Error> where
         F: FnMut(&mut Context, clean::Item),
     {
         fn render(w: File, cx: &Context, it: &clean::Item,
@@ -1264,9 +1321,9 @@ impl Context {
                 let mut item = Some(item);
                 self.recurse(name, |this| {
                     let item = item.take().unwrap();
-                    let dst = this.dst.join("index.html");
-                    let dst = try!(File::create(&dst));
-                    try!(render(dst, this, &item, false));
+                    let joint_dst = this.dst.join("index.html");
+                    let dst = try_err!(File::create(&joint_dst), &joint_dst);
+                    try_err!(render(dst, this, &item, false), &joint_dst);
 
                     let m = match item.inner {
                         clean::ModuleItem(m) => m,
@@ -1277,9 +1334,9 @@ impl Context {
                     {
                         let items = this.build_sidebar_items(&m);
                         let js_dst = this.dst.join("sidebar-items.js");
-                        let mut js_out = BufWriter::new(try!(File::create(&js_dst)));
-                        try!(write!(&mut js_out, "initSidebarItems({});",
-                                    json::as_json(&items)));
+                        let mut js_out = BufWriter::new(try_err!(File::create(&js_dst), &js_dst));
+                        try_err!(write!(&mut js_out, "initSidebarItems({});",
+                                    json::as_json(&items)), &js_dst);
                     }
 
                     for item in m.items {
@@ -1292,9 +1349,11 @@ impl Context {
             // Things which don't have names (like impls) don't get special
             // pages dedicated to them.
             _ if item.name.is_some() => {
-                let dst = self.dst.join(&item_path(&item));
-                let dst = try!(File::create(&dst));
-                render(dst, self, &item, true)
+                let joint_dst = self.dst.join(&item_path(&item));
+
+                let dst = try_err!(File::create(&joint_dst), &joint_dst);
+                try_err!(render(dst, self, &item, true), &joint_dst);
+                Ok(())
             }
 
             _ => Ok(())
@@ -1420,7 +1479,7 @@ impl<'a> Item<'a> {
                          root = root,
                          path = path[..path.len() - 1].join("/"),
                          file = item_path(self.item),
-                         goto = self.item.def_id.node))
+                         goto = self.item.def_id.index.as_usize()))
         }
     }
 }
@@ -1480,7 +1539,7 @@ impl<'a> fmt::Display for Item<'a> {
                 Some(l) => {
                     try!(write!(fmt, "<a id='src-{}' class='srclink' \
                                        href='{}' title='{}'>[src]</a>",
-                                self.item.def_id.node, l, "goto source code"));
+                                self.item.def_id.index.as_usize(), l, "goto source code"));
                 }
                 None => {}
             }
@@ -1593,8 +1652,8 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
         let s1 = i1.stability.as_ref().map(|s| s.level);
         let s2 = i2.stability.as_ref().map(|s| s.level);
         match (s1, s2) {
-            (Some(attr::Unstable), Some(attr::Stable)) => return Ordering::Greater,
-            (Some(attr::Stable), Some(attr::Unstable)) => return Ordering::Less,
+            (Some(stability::Unstable), Some(stability::Stable)) => return Ordering::Greater,
+            (Some(stability::Stable), Some(stability::Unstable)) => return Ordering::Less,
             _ => {}
         }
         i1.name.cmp(&i2.name)
@@ -1709,7 +1768,7 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Optio
                 String::new()
             };
             format!("Deprecated{}{}", since, Markdown(&reason))
-        } else if stab.level == attr::Unstable {
+        } else if stab.level == stability::Unstable {
             let unstable_extra = if show_reason {
                 match (!stab.feature.is_empty(), &cx.issue_tracker_base_url, stab.issue) {
                     (true, &Some(ref tracker_url), Some(issue_no)) =>
@@ -2336,7 +2395,7 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl) -> f
         _ => {
             if let Some(prim) = target.primitive_type() {
                 if let Some(c) = cache().primitive_locations.get(&prim) {
-                    let did = DefId { krate: *c, node: prim.to_node_id() };
+                    let did = DefId { krate: *c, index: prim.to_def_index() };
                     try!(render_assoc_items(w, cx, did, what));
                 }
             }
diff --git a/src/librustdoc/html/static/COPYRIGHT.txt b/src/librustdoc/html/static/COPYRIGHT.txt
new file mode 100644 (file)
index 0000000..2e43078
--- /dev/null
@@ -0,0 +1,64 @@
+These documentation pages include resources by third parties. This copyright
+file applies only to those resources. The following third party resources are
+included, and carry their own copyright notices and license terms:
+
+* Fira Sans (FiraSans-Regular.woff, FiraSans-Medium.woff):
+
+    Copyright (c) 2014, Mozilla Foundation https://mozilla.org/
+    with Reserved Font Name Fira Sans.
+
+    Copyright (c) 2014, Telefonica S.A.
+
+    Licensed under the SIL Open Font License, Version 1.1.
+    See FiraSans-LICENSE.txt.
+
+* Heuristica (Heuristica-Italic.woff):
+
+    Copyright 1989, 1991 Adobe Systems Incorporated. All rights reserved.
+    Utopia is either a registered trademark or trademark of Adobe Systems
+    Incorporated in the United States and/or other countries. Used under
+    license.
+
+    Copyright 2006 Han The Thanh, Vntopia font family, http://vntex.sf.net
+
+    Copyright (c) 2008-2012, Andrey V. Panov (panov@canopus.iacp.dvo.ru),
+    with Reserved Font Name Heuristica.
+
+    Licensed under the SIL Open Font License, Version 1.1.
+    See Heuristica-LICENSE.txt.
+
+* jQuery (jquery-2.1.4.min.js):
+
+    Copyright 2005, 2015 jQuery Foundation, Inc.
+    Licensed under the MIT license (see LICENSE-MIT.txt).
+
+* main.css, main.js, and playpen.js:
+
+    Copyright 2015 The Rust Developers.
+    Licensed under the Apache License, Version 2.0 (see LICENSE-APACHE.txt) or
+    the MIT license (LICENSE-MIT.txt) at your option.
+
+* normalize.css:
+
+    Copyright (c) Nicolas Gallagher and Jonathan Neal.
+    Licensed under the MIT license (see LICENSE-MIT.txt).
+
+* Source Code Pro (SourceCodePro-Regular.woff, SourceCodePro-Semibold.woff):
+
+    Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/),
+    with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark
+    of Adobe Systems Incorporated in the United States and/or other countries.
+
+    Licensed under the SIL Open Font License, Version 1.1.
+    See SourceCodePro-LICENSE.txt.
+
+* Source Serif Pro (SourceSerifPro-Regular.woff, SourceSerifPro-Bold.woff):
+
+    Copyright 2014 Adobe Systems Incorporated (http://www.adobe.com/), with
+    Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of
+    Adobe Systems Incorporated in the United States and/or other countries.
+
+    Licensed under the SIL Open Font License, Version 1.1.
+    See SourceSerifPro-LICENSE.txt.
+
+This copyright file is intended to be distributed with rustdoc output.
diff --git a/src/librustdoc/html/static/LICENSE-APACHE.txt b/src/librustdoc/html/static/LICENSE-APACHE.txt
new file mode 100644 (file)
index 0000000..16fe87b
--- /dev/null
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+   "License" shall mean the terms and conditions for use, reproduction,
+   and distribution as defined by Sections 1 through 9 of this document.
+
+   "Licensor" shall mean the copyright owner or entity authorized by
+   the copyright owner that is granting the License.
+
+   "Legal Entity" shall mean the union of the acting entity and all
+   other entities that control, are controlled by, or are under common
+   control with that entity. For the purposes of this definition,
+   "control" means (i) the power, direct or indirect, to cause the
+   direction or management of such entity, whether by contract or
+   otherwise, or (ii) ownership of fifty percent (50%) or more of the
+   outstanding shares, or (iii) beneficial ownership of such entity.
+
+   "You" (or "Your") shall mean an individual or Legal Entity
+   exercising permissions granted by this License.
+
+   "Source" form shall mean the preferred form for making modifications,
+   including but not limited to software source code, documentation
+   source, and configuration files.
+
+   "Object" form shall mean any form resulting from mechanical
+   transformation or translation of a Source form, including but
+   not limited to compiled object code, generated documentation,
+   and conversions to other media types.
+
+   "Work" shall mean the work of authorship, whether in Source or
+   Object form, made available under the License, as indicated by a
+   copyright notice that is included in or attached to the work
+   (an example is provided in the Appendix below).
+
+   "Derivative Works" shall mean any work, whether in Source or Object
+   form, that is based on (or derived from) the Work and for which the
+   editorial revisions, annotations, elaborations, or other modifications
+   represent, as a whole, an original work of authorship. For the purposes
+   of this License, Derivative Works shall not include works that remain
+   separable from, or merely link (or bind by name) to the interfaces of,
+   the Work and Derivative Works thereof.
+
+   "Contribution" shall mean any work of authorship, including
+   the original version of the Work and any modifications or additions
+   to that Work or Derivative Works thereof, that is intentionally
+   submitted to Licensor for inclusion in the Work by the copyright owner
+   or by an individual or Legal Entity authorized to submit on behalf of
+   the copyright owner. For the purposes of this definition, "submitted"
+   means any form of electronic, verbal, or written communication sent
+   to the Licensor or its representatives, including but not limited to
+   communication on electronic mailing lists, source code control systems,
+   and issue tracking systems that are managed by, or on behalf of, the
+   Licensor for the purpose of discussing and improving the Work, but
+   excluding communication that is conspicuously marked or otherwise
+   designated in writing by the copyright owner as "Not a Contribution."
+
+   "Contributor" shall mean Licensor and any individual or Legal Entity
+   on behalf of whom a Contribution has been received by Licensor and
+   subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   copyright license to reproduce, prepare Derivative Works of,
+   publicly display, publicly perform, sublicense, and distribute the
+   Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+   this License, each Contributor hereby grants to You a perpetual,
+   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+   (except as stated in this section) patent license to make, have made,
+   use, offer to sell, sell, import, and otherwise transfer the Work,
+   where such license applies only to those patent claims licensable
+   by such Contributor that are necessarily infringed by their
+   Contribution(s) alone or by combination of their Contribution(s)
+   with the Work to which such Contribution(s) was submitted. If You
+   institute patent litigation against any entity (including a
+   cross-claim or counterclaim in a lawsuit) alleging that the Work
+   or a Contribution incorporated within the Work constitutes direct
+   or contributory patent infringement, then any patent licenses
+   granted to You under this License for that Work shall terminate
+   as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+   Work or Derivative Works thereof in any medium, with or without
+   modifications, and in Source or Object form, provided that You
+   meet the following conditions:
+
+   (a) You must give any other recipients of the Work or
+       Derivative Works a copy of this License; and
+
+   (b) You must cause any modified files to carry prominent notices
+       stating that You changed the files; and
+
+   (c) You must retain, in the Source form of any Derivative Works
+       that You distribute, all copyright, patent, trademark, and
+       attribution notices from the Source form of the Work,
+       excluding those notices that do not pertain to any part of
+       the Derivative Works; and
+
+   (d) If the Work includes a "NOTICE" text file as part of its
+       distribution, then any Derivative Works that You distribute must
+       include a readable copy of the attribution notices contained
+       within such NOTICE file, excluding those notices that do not
+       pertain to any part of the Derivative Works, in at least one
+       of the following places: within a NOTICE text file distributed
+       as part of the Derivative Works; within the Source form or
+       documentation, if provided along with the Derivative Works; or,
+       within a display generated by the Derivative Works, if and
+       wherever such third-party notices normally appear. The contents
+       of the NOTICE file are for informational purposes only and
+       do not modify the License. You may add Your own attribution
+       notices within Derivative Works that You distribute, alongside
+       or as an addendum to the NOTICE text from the Work, provided
+       that such additional attribution notices cannot be construed
+       as modifying the License.
+
+   You may add Your own copyright statement to Your modifications and
+   may provide additional or different license terms and conditions
+   for use, reproduction, or distribution of Your modifications, or
+   for any such Derivative Works as a whole, provided Your use,
+   reproduction, and distribution of the Work otherwise complies with
+   the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+   any Contribution intentionally submitted for inclusion in the Work
+   by You to the Licensor shall be under the terms and conditions of
+   this License, without any additional terms or conditions.
+   Notwithstanding the above, nothing herein shall supersede or modify
+   the terms of any separate license agreement you may have executed
+   with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+   names, trademarks, service marks, or product names of the Licensor,
+   except as required for reasonable and customary use in describing the
+   origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+   agreed to in writing, Licensor provides the Work (and each
+   Contributor provides its Contributions) on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+   implied, including, without limitation, any warranties or conditions
+   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+   PARTICULAR PURPOSE. You are solely responsible for determining the
+   appropriateness of using or redistributing the Work and assume any
+   risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+   whether in tort (including negligence), contract, or otherwise,
+   unless required by applicable law (such as deliberate and grossly
+   negligent acts) or agreed to in writing, shall any Contributor be
+   liable to You for damages, including any direct, indirect, special,
+   incidental, or consequential damages of any character arising as a
+   result of this License or out of the use or inability to use the
+   Work (including but not limited to damages for loss of goodwill,
+   work stoppage, computer failure or malfunction, or any and all
+   other commercial damages or losses), even if such Contributor
+   has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+   the Work or Derivative Works thereof, You may choose to offer,
+   and charge a fee for, acceptance of support, warranty, indemnity,
+   or other liability obligations and/or rights consistent with this
+   License. However, in accepting such obligations, You may act only
+   on Your own behalf and on Your sole responsibility, not on behalf
+   of any other Contributor, and only if You agree to indemnify,
+   defend, and hold each Contributor harmless for any liability
+   incurred by, or claims asserted against, such Contributor by reason
+   of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+   To apply the Apache License to your work, attach the following
+   boilerplate notice, with the fields enclosed by brackets "[]"
+   replaced with your own identifying information. (Don't include
+   the brackets!)  The text should be enclosed in the appropriate
+   comment syntax for the file format. We also recommend that a
+   file or class name and description of purpose be included on the
+   same "printed page" as the copyright notice for easier
+   identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/src/librustdoc/html/static/LICENSE-MIT.txt b/src/librustdoc/html/static/LICENSE-MIT.txt
new file mode 100644 (file)
index 0000000..31aa793
--- /dev/null
@@ -0,0 +1,23 @@
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
index e6b653cbd5c348cc9c9d96caade1da526e16b3b6..5e27eab8575ee9b020bb73e8da918f18c7cabfb2 100644 (file)
@@ -9,6 +9,8 @@
  * option. This file may not be copied, modified, or distributed
  * except according to those terms.
  */
+
+/* See FiraSans-LICENSE.txt for the Fira Sans license. */
 @font-face {
     font-family: 'Fira Sans';
     font-style: normal;
@@ -21,6 +23,9 @@
     font-weight: 500;
     src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff');
 }
+
+/* See SourceSerifPro-LICENSE.txt for the Source Serif Pro license and
+ * Heuristica-LICENSE.txt for the Heuristica license. */
 @font-face {
     font-family: 'Source Serif Pro';
     font-style: normal;
@@ -39,6 +44,8 @@
     font-weight: 700;
     src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.woff") format('woff');
 }
+
+/* See SourceCodePro-LICENSE.txt for the Source Code Pro license. */
 @font-face {
     font-family: 'Source Code Pro';
     font-style: normal;
@@ -552,14 +559,17 @@ pre.rust .lifetime { color: #B76514; }
 
 .rusttest { display: none; }
 pre.rust { position: relative; }
-.test-arrow {
+a.test-arrow {
     display: inline-block;
     position: absolute;
-    top: 0;
-    right: 10px;
-    font-size: 150%;
-    -webkit-transform: scaleX(-1);
-    transform: scaleX(-1);
+
+    background-color: #4e8bca;
+    color: #f5f5f5;
+    padding: 5px 10px 5px 10px;
+    border-radius: 5px;
+    font-size: 130%;
+    top: 5px;
+    right: 5px;
 }
 
 .methods .section-header {
index 9d84d4ea3c1a995d42a44bb95f57f6a4c937f4ed..5a6d76168322402f27d991b96a67fa1dacb8ecd2 100644 (file)
@@ -54,7 +54,8 @@
     }
 
     function browserSupportsHistoryApi() {
-        return window.history && typeof window.history.pushState === "function";
+        return document.location.protocol != "file:" &&
+          window.history && typeof window.history.pushState === "function";
     }
 
     function highlightSourceLines(ev) {
     $(document).on("keypress", handleShortcut);
     $(document).on("keydown", handleShortcut);
     $(document).on("click", function(ev) {
-        if (!$(e.target).closest("#help > div").length) {
+        if (!$(ev.target).closest("#help > div").length) {
             $("#help").addClass("hidden");
             $("body").removeClass("blur");
         }
                 if ((aaa.item.ty === TY_PRIMITIVE) && (bbb.item.ty !== TY_PRIMITIVE)) {
                     return -1;
                 }
+                if ((bbb.item.ty === TY_PRIMITIVE) && (aaa.item.ty !== TY_PRIMITIVE)) {
+                    return 1;
+                }
 
                 // sort by description (no description goes later)
                 a = (aaa.item.desc === '');
                 var $active = $results.filter('.highlighted');
 
                 if (e.which === 38) { // up
-                    e.preventDefault();
                     if (!$active.length || !$active.prev()) {
                         return;
                     }
                     $active.prev().addClass('highlighted');
                     $active.removeClass('highlighted');
                 } else if (e.which === 40) { // down
-                    e.preventDefault();
                     if (!$active.length) {
                         $results.first().addClass('highlighted');
                     } else if ($active.next().length) {
                         $active.removeClass('highlighted');
                     }
                 } else if (e.which === 13) { // return
-                    e.preventDefault();
                     if ($active.length) {
                         document.location.href = $active.find('a').prop('href');
                     }
                         displayPath = item.path + '::';
                         href = rootPath + item.path.replace(/::/g, '/') +
                                '/index.html';
+                    } else if (type === "primitive") {
+                        displayPath = "";
+                        href = rootPath + item.path.replace(/::/g, '/') +
+                               '/' + type + '.' + name + '.html';
                     } else if (item.parent !== undefined) {
                         var myparent = item.parent;
                         var anchor = '#' + type + '.' + name;
         }
 
         function startSearch() {
-            var keyUpTimeout;
-            $('.do-search').on('click', search);
-            $('.search-input').on('keyup', function() {
-                clearTimeout(keyUpTimeout);
-                keyUpTimeout = setTimeout(search, 500);
+            var searchTimeout;
+            $(".search-input").on("keyup input",function() {
+                clearTimeout(searchTimeout);
+                if ($(this).val().length === 0) {
+                    window.history.replaceState("", "std - Rust", "?search=");
+                    $('#main.content').removeClass('hidden');
+                    $('#search.content').addClass('hidden');
+                } else {
+                    searchTimeout = setTimeout(search, 500);
+                }
+            });
+            $('.search-form').on('submit', function(e){
+                e.preventDefault();
+                clearTimeout(searchTimeout);
+                search();
+            });
+            $('.search-input').on('change paste', function(e) {
+                // Do NOT e.preventDefault() here. It will prevent pasting.
+                clearTimeout(searchTimeout);
+                // zero-timeout necessary here because at the time of event handler execution the
+                // pasted content is not in the input field yet. Shouldn’t make any difference for
+                // change, though.
+                setTimeout(search, 0);
             });
 
             // Push and pop states are used to add search results to the browser
index ef8bdf5e2ce9738146d429b227f1c8a5b817777d..8f8a753b06c96b5db6b40de0010fec6d7ffeab50 100644 (file)
@@ -12,6 +12,8 @@
 /*globals $: true, rootPath: true */
 
 document.addEventListener('DOMContentLoaded', function() {
+    'use strict';
+
     if (!window.playgroundUrl) {
         return;
     }
@@ -26,8 +28,8 @@ document.addEventListener('DOMContentLoaded', function() {
             }
 
             var a = document.createElement('a');
-            a.textContent = '⇱';
             a.setAttribute('class', 'test-arrow');
+            a.textContent = 'Run';
 
             var code = el.previousElementSibling.textContent;
 
index 8f3e63820dac9ca30382c143a562278539b9e0b8..53be8b5bc06c8e2cd440ce0c90ea397c41f127d8 100644 (file)
@@ -55,8 +55,8 @@ pub struct TocBuilder {
     /// strictly increasing (i.e. chain[0].level < chain[1].level <
     /// ...) with each entry being the most recent occurrence of a
     /// heading with that level (it doesn't include the most recent
-    /// occurrences of every level, just, if *is* in `chain` then is is
-    /// the most recent one).
+    /// occurrences of every level, just, if it *is* in `chain` then
+    /// it is the most recent one).
     ///
     /// We also have `chain[0].level <= top_level.entries[last]`.
     chain: Vec<TocEntry>
index efe5a73fad216eeabe5f56a07e221e7e76d7aa4b..db0da3764ba22039cbef4e913e23ef7b64b0f459 100644 (file)
@@ -24,7 +24,6 @@
 #![feature(box_syntax)]
 #![feature(dynamic_lib)]
 #![feature(libc)]
-#![feature(path_ext)]
 #![feature(path_relative_from)]
 #![feature(rustc_private)]
 #![feature(set_stdio)]
@@ -211,7 +210,7 @@ pub fn main_args(args: &[String]) -> isize {
         for &(name, _, description) in PASSES {
             println!("{:>20} - {}", name, description);
         }
-        println!("{}", "\nDefault passes for rustdoc:"); // FIXME: #9970
+        println!("\nDefault passes for rustdoc:");
         for &name in DEFAULT_PASSES {
             println!("{:>20}", name);
         }
index 8a57a50bdea4196959ebec022b7161ff740d9d89..1957f1efa4774ebecd524423814108a3a326b941 100644 (file)
@@ -8,12 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::collections::HashSet;
-use rustc::util::nodemap::NodeSet;
+use rustc::util::nodemap::DefIdSet;
 use std::cmp;
 use std::string::String;
 use std::usize;
-use syntax::ast;
 use rustc_front::hir;
 
 use clean;
@@ -24,18 +22,18 @@ use fold::DocFolder;
 
 /// Strip items marked `#[doc(hidden)]`
 pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult {
-    let mut stripped = HashSet::new();
+    let mut stripped = DefIdSet();
 
     // strip all #[doc(hidden)] items
     let krate = {
         struct Stripper<'a> {
-            stripped: &'a mut HashSet<ast::NodeId>
-        };
+            stripped: &'a mut DefIdSet
+        }
         impl<'a> fold::DocFolder for Stripper<'a> {
             fn fold_item(&mut self, i: Item) -> Option<Item> {
                 if i.is_hidden_from_doc() {
                     debug!("found one in strip_hidden; removing");
-                    self.stripped.insert(i.def_id.node);
+                    self.stripped.insert(i.def_id);
 
                     // use a dedicated hidden item for given item type if any
                     match i.inner {
@@ -61,8 +59,8 @@ pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult {
     // strip any traits implemented on stripped items
     let krate = {
         struct ImplStripper<'a> {
-            stripped: &'a mut HashSet<ast::NodeId>
-        };
+            stripped: &'a mut DefIdSet
+        }
         impl<'a> fold::DocFolder for ImplStripper<'a> {
             fn fold_item(&mut self, i: Item) -> Option<Item> {
                 if let clean::ImplItem(clean::Impl{
@@ -70,12 +68,12 @@ pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult {
                            ref trait_, ..
                 }) = i.inner {
                     // Impls for stripped types don't need to exist
-                    if self.stripped.contains(&did.node) {
+                    if self.stripped.contains(&did) {
                         return None;
                     }
                     // Impls of stripped traits also don't need to exist
                     if let Some(clean::ResolvedPath { did, .. }) = *trait_ {
-                        if self.stripped.contains(&did.node) {
+                        if self.stripped.contains(&did) {
                             return None;
                         }
                     }
@@ -94,7 +92,7 @@ pub fn strip_hidden(krate: clean::Crate) -> plugins::PluginResult {
 /// crate, specified by the `xcrate` flag.
 pub fn strip_private(mut krate: clean::Crate) -> plugins::PluginResult {
     // This stripper collects all *retained* nodes.
-    let mut retained = HashSet::new();
+    let mut retained = DefIdSet();
     let analysis = super::ANALYSISKEY.with(|a| a.clone());
     let analysis = analysis.borrow();
     let analysis = analysis.as_ref().unwrap();
@@ -118,8 +116,8 @@ pub fn strip_private(mut krate: clean::Crate) -> plugins::PluginResult {
 }
 
 struct Stripper<'a> {
-    retained: &'a mut HashSet<ast::NodeId>,
-    exported_items: &'a NodeSet,
+    retained: &'a mut DefIdSet,
+    exported_items: &'a DefIdSet,
 }
 
 impl<'a> fold::DocFolder for Stripper<'a> {
@@ -132,7 +130,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
             clean::VariantItem(..) | clean::MethodItem(..) |
             clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) => {
                 if i.def_id.is_local() {
-                    if !self.exported_items.contains(&i.def_id.node) {
+                    if !self.exported_items.contains(&i.def_id) {
                         return None;
                     }
                     // Traits are in exported_items even when they're totally private.
@@ -143,8 +141,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
             }
 
             clean::ConstantItem(..) => {
-                if i.def_id.is_local() &&
-                   !self.exported_items.contains(&i.def_id.node) {
+                if i.def_id.is_local() && !self.exported_items.contains(&i.def_id) {
                     return None;
                 }
             }
@@ -171,8 +168,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
             clean::ImplItem(clean::Impl{
                 for_: clean::ResolvedPath{ did, .. }, ..
             }) => {
-                if did.is_local() &&
-                   !self.exported_items.contains(&did.node) {
+                if did.is_local() && !self.exported_items.contains(&did) {
                     return None;
                 }
             }
@@ -205,7 +201,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
         };
 
         let i = if fastreturn {
-            self.retained.insert(i.def_id.node);
+            self.retained.insert(i.def_id);
             return Some(i);
         } else {
             self.fold_item_recur(i)
@@ -220,7 +216,7 @@ impl<'a> fold::DocFolder for Stripper<'a> {
                            i.doc_value().is_none() => None,
                     clean::ImplItem(ref i) if i.items.is_empty() => None,
                     _ => {
-                        self.retained.insert(i.def_id.node);
+                        self.retained.insert(i.def_id);
                         Some(i)
                     }
                 }
@@ -231,14 +227,13 @@ impl<'a> fold::DocFolder for Stripper<'a> {
 }
 
 // This stripper discards all private impls of traits
-struct ImplStripper<'a>(&'a HashSet<ast::NodeId>);
+struct ImplStripper<'a>(&'a DefIdSet);
 impl<'a> fold::DocFolder for ImplStripper<'a> {
     fn fold_item(&mut self, i: Item) -> Option<Item> {
         if let clean::ImplItem(ref imp) = i.inner {
             match imp.trait_ {
                 Some(clean::ResolvedPath{ did, .. }) => {
-                    let ImplStripper(s) = *self;
-                    if did.is_local() && !s.contains(&did.node) {
+                    if did.is_local() && !self.0.contains(&did) {
                         return None;
                     }
                 }
index a81787dad77744889e6d5691621d387c756d9dc1..7292ea5377e25d8bb0a293030c76c448c1484dd0 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(deprecated)]
+
 use clean;
 
 use std::dynamic_lib as dl;
index 95215cf2d5caf76985e1ff49cf1f9a9f53f2ffba..cbaff95dfddd730fddb73369a0bcd6fb8f30aa82 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(deprecated)]
+
 use std::cell::{RefCell, Cell};
 use std::collections::{HashSet, HashMap};
 use std::dynamic_lib::DynamicLibrary;
@@ -22,10 +24,11 @@ use std::sync::{Arc, Mutex};
 
 use testing;
 use rustc_lint;
+use rustc::front::map as hir_map;
 use rustc::session::{self, config};
-use rustc::session::config::get_unstable_features_setting;
+use rustc::session::config::{get_unstable_features_setting, OutputType};
 use rustc::session::search_paths::{SearchPaths, PathKind};
-use rustc_front::lowering::lower_crate;
+use rustc_front::lowering::{lower_crate, LoweringContext};
 use rustc_back::tempdir::TempDir;
 use rustc_driver::{driver, Compilation};
 use syntax::codemap::CodeMap;
@@ -82,13 +85,17 @@ pub fn run(input: &str,
                                                      "rustdoc-test", None)
         .expect("phase_2_configure_and_expand aborted in rustdoc!");
     let krate = driver::assign_node_ids(&sess, krate);
-    let krate = lower_crate(&krate);
+    let lcx = LoweringContext::new(&sess, Some(&krate));
+    let krate = lower_crate(&lcx, &krate);
 
     let opts = scrape_test_config(&krate);
 
+    let mut forest = hir_map::Forest::new(krate);
+    let map = hir_map::map_crate(&mut forest);
+
     let ctx = core::DocContext {
-        krate: &krate,
-        maybe_typed: core::NotTyped(sess),
+        map: &map,
+        maybe_typed: core::NotTyped(&sess),
         input: input,
         external_paths: RefCell::new(Some(HashMap::new())),
         external_traits: RefCell::new(None),
@@ -99,7 +106,7 @@ pub fn run(input: &str,
     };
 
     let mut v = RustdocVisitor::new(&ctx, None);
-    v.visit(ctx.krate);
+    v.visit(ctx.map.krate());
     let mut krate = v.clean(&ctx);
     match crate_name {
         Some(name) => krate.name = name,
@@ -124,8 +131,8 @@ pub fn run(input: &str,
 
 // Look for #![doc(test(no_crate_inject))], used by crates in the std facade
 fn scrape_test_config(krate: &::rustc_front::hir::Crate) -> TestOptions {
-    use rustc_front::attr::AttrMetaMethods;
-    use rustc_front::print::pprust;
+    use syntax::attr::AttrMetaMethods;
+    use syntax::print::pprust;
 
     let mut opts = TestOptions {
         no_crate_inject: false,
@@ -163,13 +170,15 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
     // never wrap the test in `fn main() { ... }`
     let test = maketest(test, Some(cratename), as_test_harness, opts);
     let input = config::Input::Str(test.to_string());
+    let mut outputs = HashMap::new();
+    outputs.insert(OutputType::Exe, None);
 
     let sessopts = config::Options {
         maybe_sysroot: Some(env::current_exe().unwrap().parent().unwrap()
                                               .parent().unwrap().to_path_buf()),
         search_paths: libs,
         crate_types: vec!(config::CrateTypeExecutable),
-        output_types: vec!(config::OutputTypeExe),
+        output_types: outputs,
         externs: externs,
         cg: config::CodegenOptions {
             prefer_dynamic: true,
index 978b572ac9372e539ca496cdb7808b7228721e8f..b6c93bf00af5fa1f8255a9d9fa2a3fe95485f159 100644 (file)
@@ -16,14 +16,13 @@ use std::mem;
 
 use syntax::abi;
 use syntax::ast;
+use syntax::attr;
+use syntax::attr::AttrMetaMethods;
 use syntax::codemap::Span;
 
 use rustc::front::map as hir_map;
-use rustc::middle::def_id::DefId;
 use rustc::middle::stability;
 
-use rustc_front::attr;
-use rustc_front::attr::AttrMetaMethods;
 use rustc_front::hir;
 
 use core;
@@ -39,7 +38,7 @@ use doctree::*;
 
 pub struct RustdocVisitor<'a, 'tcx: 'a> {
     pub module: Module,
-    pub attrs: Vec<hir::Attribute>,
+    pub attrs: Vec<ast::Attribute>,
     pub cx: &'a core::DocContext<'a, 'tcx>,
     pub analysis: Option<&'a core::CrateAnalysis>,
     view_item_stack: HashSet<ast::NodeId>,
@@ -63,8 +62,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
     }
 
     fn stability(&self, id: ast::NodeId) -> Option<attr::Stability> {
-        self.cx.tcx_opt().and_then(
-            |tcx| stability::lookup(tcx, DefId::local(id)).map(|x| x.clone()))
+        self.cx.tcx_opt().and_then(|tcx| {
+            self.cx.map.opt_local_def_id(id)
+                       .and_then(|def_id| stability::lookup(tcx, def_id))
+                       .cloned()
+        })
     }
 
     pub fn visit(&mut self, krate: &hir::Crate) {
@@ -82,8 +84,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         self.module.is_crate = true;
     }
 
-    pub fn visit_struct_def(&mut self, item: &hir::Item,
-                            name: ast::Ident, sd: &hir::StructDef,
+    pub fn visit_variant_data(&mut self, item: &hir::Item,
+                            name: ast::Name, sd: &hir::VariantData,
                             generics: &hir::Generics) -> Struct {
         debug!("Visiting struct");
         let struct_type = struct_type_from_def(&*sd);
@@ -95,13 +97,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             stab: self.stability(item.id),
             attrs: item.attrs.clone(),
             generics: generics.clone(),
-            fields: sd.fields.clone(),
+            fields: sd.fields().iter().cloned().collect(),
             whence: item.span
         }
     }
 
     pub fn visit_enum_def(&mut self, it: &hir::Item,
-                          name: ast::Ident, def: &hir::EnumDef,
+                          name: ast::Name, def: &hir::EnumDef,
                           params: &hir::Generics) -> Enum {
         debug!("Visiting enum");
         Enum {
@@ -109,10 +111,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             variants: def.variants.iter().map(|v| Variant {
                 name: v.node.name,
                 attrs: v.node.attrs.clone(),
-                vis: v.node.vis,
-                stab: self.stability(v.node.id),
-                id: v.node.id,
-                kind: v.node.kind.clone(),
+                stab: self.stability(v.node.data.id()),
+                def: v.node.data.clone(),
                 whence: v.span,
             }).collect(),
             vis: it.vis,
@@ -125,7 +125,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
     }
 
     pub fn visit_fn(&mut self, item: &hir::Item,
-                    name: ast::Ident, fd: &hir::FnDecl,
+                    name: ast::Name, fd: &hir::FnDecl,
                     unsafety: &hir::Unsafety,
                     constness: hir::Constness,
                     abi: &abi::Abi,
@@ -146,10 +146,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         }
     }
 
-    pub fn visit_mod_contents(&mut self, span: Span, attrs: Vec<hir::Attribute> ,
+    pub fn visit_mod_contents(&mut self, span: Span, attrs: Vec<ast::Attribute> ,
                               vis: hir::Visibility, id: ast::NodeId,
                               m: &hir::Mod,
-                              name: Option<ast::Ident>) -> Module {
+                              name: Option<ast::Name>) -> Module {
         let mut om = Module::new(name);
         om.where_outer = span;
         om.where_inner = m.inner;
@@ -200,23 +200,25 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
 
     }
 
-    fn resolve_id(&mut self, id: ast::NodeId, renamed: Option<ast::Ident>,
+    fn resolve_id(&mut self, id: ast::NodeId, renamed: Option<ast::Name>,
                   glob: bool, om: &mut Module, please_inline: bool) -> bool {
         let tcx = match self.cx.tcx_opt() {
             Some(tcx) => tcx,
             None => return false
         };
         let def = tcx.def_map.borrow()[&id].def_id();
-        if !def.is_local() { return false }
+        let def_node_id = match tcx.map.as_local_node_id(def) {
+            Some(n) => n, None => return false
+        };
         let analysis = match self.analysis {
             Some(analysis) => analysis, None => return false
         };
-        if !please_inline && analysis.public_items.contains(&def.node) {
+        if !please_inline && analysis.public_items.contains(&def) {
             return false
         }
-        if !self.view_item_stack.insert(def.node) { return false }
+        if !self.view_item_stack.insert(def_node_id) { return false }
 
-        let ret = match tcx.map.get(def.node) {
+        let ret = match tcx.map.get(def_node_id) {
             hir_map::NodeItem(it) => {
                 if glob {
                     let prev = mem::replace(&mut self.inlining_from_glob, true);
@@ -237,14 +239,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             }
             _ => false,
         };
-        self.view_item_stack.remove(&id);
+        self.view_item_stack.remove(&def_node_id);
         return ret;
     }
 
     pub fn visit_item(&mut self, item: &hir::Item,
-                      renamed: Option<ast::Ident>, om: &mut Module) {
+                      renamed: Option<ast::Name>, om: &mut Module) {
         debug!("Visiting item {:?}", item);
-        let name = renamed.unwrap_or(item.ident);
+        let name = renamed.unwrap_or(item.name);
         match item.node {
             hir::ItemExternCrate(ref p) => {
                 let path = match *p {
@@ -296,7 +298,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             hir::ItemEnum(ref ed, ref gen) =>
                 om.enums.push(self.visit_enum_def(item, name, ed, gen)),
             hir::ItemStruct(ref sd, ref gen) =>
-                om.structs.push(self.visit_struct_def(item, name, &**sd, gen)),
+                om.structs.push(self.visit_variant_data(item, name, sd, gen)),
             hir::ItemFn(ref fd, ref unsafety, constness, ref abi, ref gen, _) =>
                 om.fns.push(self.visit_fn(item, name, &**fd, unsafety,
                                           constness, abi, gen)),
@@ -399,7 +401,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         Macro {
             id: def.id,
             attrs: def.attrs.clone(),
-            name: def.ident,
+            name: def.name,
             whence: def.span,
             stab: self.stability(def.id),
             imported_from: def.imported_from,
index 4bcaa4b5dbc75cc2c5f83b4f3fc2cf8ba5c43d81..452feed3cdb4effa751e10616edabbd5867e9e98 100644 (file)
@@ -76,8 +76,7 @@
 //! Create a struct called `TestStruct` and serialize and deserialize it to and from JSON using the
 //! serialization API, using the derived serialization code.
 //!
-//! ```notrust
-//! // FIXME(#19470): this cannot be ```rust``` because it fails orphan checking at the moment
+//! ```rust
 //! extern crate serialize;
 //! use serialize::json;
 //!
 //!
 //! ### Simple example of `ToJson` usage
 //!
-//! ```notrust
-//! // FIXME(#19470): this cannot be ```rust``` because it fails orphan checking at the moment
+//! ```rust
 //! extern crate serialize;
 //! use serialize::json::{self, ToJson, Json};
 //!
 //!
 //! ### Verbose example of `ToJson` usage
 //!
-//! ```notrust
-//! // FIXME(#19470): this cannot be ```rust``` because it fails orphan checking at the moment
+//! ```rust
 //! extern crate serialize;
 //! use std::collections::BTreeMap;
 //! use serialize::json::{self, Json, ToJson};
index 4ad8fce8120aa2318db78c476b2aad8c3f46bf03..7c6add80337c01f218fbaa51314beeaf929533e2 100644 (file)
@@ -207,7 +207,7 @@ fn test_resize_policy() {
 /// The hashes are all keyed by the thread-local random number generator
 /// on creation by default. This means that the ordering of the keys is
 /// randomized, but makes the tables more resistant to
-/// denial-of-service attacks (Hash DoS). This behaviour can be
+/// denial-of-service attacks (Hash DoS). This behavior can be
 /// overridden with one of the constructors.
 ///
 /// It is required that the keys implement the `Eq` and `Hash` traits, although
@@ -324,7 +324,7 @@ fn search_hashed<K, V, M, F>(table: M,
     F: FnMut(&K) -> bool,
 {
     // This is the only function where capacity can be zero. To avoid
-    // undefined behaviour when Bucket::new gets the raw bucket in this
+    // undefined behavior when Bucket::new gets the raw bucket in this
     // case, immediately return the appropriate search result.
     if table.capacity() == 0 {
         return TableRef(table);
@@ -1101,8 +1101,14 @@ impl<K, V, S> HashMap<K, V, S>
         self.search_mut(k).map(|bucket| bucket.into_mut_refs().1)
     }
 
-    /// Inserts a key-value pair into the map. If the key already had a value
-    /// present in the map, that value is returned. Otherwise, `None` is returned.
+    /// Inserts a key-value pair into the map.
+    ///
+    /// If the map did not have this key present, `None` is returned.
+    ///
+    /// If the map did have this key present, that value is returned, and the
+    /// entry is not updated. See the [module-level documentation] for more.
+    ///
+    /// [module-level documentation]: index.html#insert-and-complex-keys
     ///
     /// # Examples
     ///
index 7264b5827c4fb0d46d9ff6719824e0ebda671614..1f6b349399610a251041fe10d9c41fb092628047 100644 (file)
@@ -540,8 +540,14 @@ impl<T, S> HashSet<T, S>
         other.is_subset(self)
     }
 
-    /// Adds a value to the set. Returns `true` if the value was not already
-    /// present in the set.
+    /// Adds a value to the set.
+    ///
+    /// If the set did not have a value present, `true` is returned.
+    ///
+    /// If the set did have this key present, that value is returned, and the
+    /// entry is not updated. See the [module-level documentation] for more.
+    ///
+    /// [module-level documentation]: index.html#insert-and-complex-keys
     ///
     /// # Examples
     ///
index f8bd791f6819c16cdc14f5e3ffce7e3a029c36f7..e8796dd10b4f866cbf3b87e69bd23104430fe663 100644 (file)
@@ -958,7 +958,7 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
 
 impl<'a, K: 'a, V: 'a> Drop for Drain<'a, K, V> {
     fn drop(&mut self) {
-        for _ in self.by_ref() {}
+        for _ in self {}
     }
 }
 
@@ -999,6 +999,7 @@ impl<K: Clone, V: Clone> Clone for RawTable<K, V> {
 }
 
 impl<K, V> Drop for RawTable<K, V> {
+    #[unsafe_destructor_blind_to_params]
     fn drop(&mut self) {
         if self.capacity == 0 || self.capacity == mem::POST_DROP_USIZE {
             return;
index 83e28e39a72536e04420a7f311f45229e6e6539f..71d9fbfaa3e801506d875048e9773f7bdff27015 100644 (file)
 //! ```
 //! use std::collections::btree_map::BTreeMap;
 //!
-//! // A client of the bar. They have an id and a blood alcohol level.
-//! struct Person { id: u32, blood_alcohol: f32 }
+//! // A client of the bar. They have a blood alcohol level.
+//! struct Person { blood_alcohol: f32 }
 //!
 //! // All the orders made to the bar, by client id.
 //! let orders = vec![1,2,1,2,3,4,1,2,2,3,4,1,1,1];
 //! for id in orders {
 //!     // If this is the first time we've seen this customer, initialize them
 //!     // with no blood alcohol. Otherwise, just retrieve them.
-//!     let person = blood_alcohol.entry(id).or_insert(Person{id: id, blood_alcohol: 0.0});
+//!     let person = blood_alcohol.entry(id).or_insert(Person { blood_alcohol: 0.0 });
 //!
 //!     // Reduce their blood alcohol level. It takes time to order and drink a beer!
 //!     person.blood_alcohol *= 0.9;
 //!     // Check if they're sober enough to have another beer.
 //!     if person.blood_alcohol > 0.3 {
 //!         // Too drunk... for now.
-//!         println!("Sorry {}, I have to cut you off", person.id);
+//!         println!("Sorry {}, I have to cut you off", id);
 //!     } else {
 //!         // Have another!
 //!         person.blood_alcohol += 0.1;
 //!     }
 //! }
 //! ```
+//!
+//! # Insert and complex keys
+//!
+//! If we have a more complex key, calls to `insert()` will
+//! not update the value of the key. For example:
+//!
+//! ```
+//! use std::cmp::Ordering;
+//! use std::collections::BTreeMap;
+//! use std::hash::{Hash, Hasher};
+//!
+//! #[derive(Debug)]
+//! struct Foo {
+//!     a: u32,
+//!     b: &'static str,
+//! }
+//!
+//! // we will compare `Foo`s by their `a` value only.
+//! impl PartialEq for Foo {
+//!     fn eq(&self, other: &Self) -> bool { self.a == other.a }
+//! }
+//!
+//! impl Eq for Foo {}
+//!
+//! // we will hash `Foo`s by their `a` value only.
+//! impl Hash for Foo {
+//!     fn hash<H: Hasher>(&self, h: &mut H) { self.a.hash(h); }
+//! }
+//!
+//! impl PartialOrd for Foo {
+//!     fn partial_cmp(&self, other: &Self) -> Option<Ordering> { self.a.partial_cmp(&other.a) }
+//! }
+//!
+//! impl Ord for Foo {
+//!     fn cmp(&self, other: &Self) -> Ordering { self.a.cmp(&other.a) }
+//! }
+//!
+//! let mut map = BTreeMap::new();
+//! map.insert(Foo { a: 1, b: "baz" }, ());
+//!
+//! // We already have a Foo with an a of 1, so this will be updating the value.
+//! map.insert(Foo { a: 1, b: "xyz" }, ());
+//!
+//! // ... but the key hasn't changed. b is still "baz", not "xyz"
+//! assert_eq!(map.keys().next().unwrap().b, "baz");
+//! ```
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index 7801662ff25f924a8df2069ecd7216b772ceb96a..684a300560644483fd78e2e07b517dc7ff28843a 100644 (file)
             reason = "API has not been scrutinized and is highly likely to \
                       either disappear or change",
             issue = "27810")]
+#![deprecated(since = "1.5.0", reason = "replaced with crates.io crates")]
 #![allow(missing_docs)]
+#![allow(deprecated)]
 
 use prelude::v1::*;
 
 use env;
 use ffi::{CString, OsString};
-use mem;
 use path::{Path, PathBuf};
 
 pub struct DynamicLibrary {
@@ -114,7 +115,7 @@ impl DynamicLibrary {
         // the destructor does not run.
         match maybe_symbol_value {
             Err(err) => Err(err),
-            Ok(symbol_value) => Ok(mem::transmute(symbol_value))
+            Ok(symbol_value) => Ok(symbol_value as *mut T)
         }
     }
 }
index 3447d1683a800347fbc7fc5fa79d35583096cb1c..1f6761b54cb3216d27cfe30a2d667bc53d8b7f7a 100644 (file)
@@ -260,6 +260,12 @@ impl Error for VarError {
 ///  - [Austin Group Bugzilla](http://austingroupbugs.net/view.php?id=188)
 ///  - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2)
 ///
+/// # Panics
+///
+/// This function may panic if `key` is empty, contains an ASCII equals sign
+/// `'='` or the NUL character `'\0'`, or when the value contains the NUL
+/// character.
+///
 /// # Examples
 ///
 /// ```
@@ -292,6 +298,12 @@ fn _set_var(k: &OsStr, v: &OsStr) {
 ///  - [Austin Group Bugzilla](http://austingroupbugs.net/view.php?id=188)
 ///  - [GNU C library Bugzilla](https://sourceware.org/bugzilla/show_bug.cgi?id=15607#c2)
 ///
+/// # Panics
+///
+/// This function may panic if `key` is empty, contains an ASCII equals sign
+/// `'='` or the NUL character `'\0'`, or when the value contains the NUL
+/// character.
+///
 /// # Examples
 ///
 /// ```
@@ -416,7 +428,10 @@ impl Error for JoinPathsError {
 /// Returns the value of the 'HOME' environment variable if it is
 /// set and not equal to the empty string. Otherwise, returns the value of the
 /// 'USERPROFILE' environment variable if it is set and not equal to the empty
-/// string.
+/// string. If both do not exist, [`GetUserProfileDirectory`][msdn] is used to
+/// return the appropriate path.
+///
+/// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/bb762280(v=vs.85).aspx
 ///
 /// # Examples
 ///
@@ -442,7 +457,11 @@ pub fn home_dir() -> Option<PathBuf> {
 ///
 /// On Windows, returns the value of, in order, the 'TMP', 'TEMP',
 /// 'USERPROFILE' environment variable  if any are set and not the empty
-/// string. Otherwise, tmpdir returns the path to the Windows directory.
+/// string. Otherwise, tmpdir returns the path to the Windows directory. This
+/// behavior is identical to that of [GetTempPath][msdn], which this function
+/// uses internally.
+///
+/// [msdn]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa364992(v=vs.85).aspx
 ///
 /// ```
 /// use std::env;
index 7c9c2066ae93ae982fb883ce579dd4d8642fa4c7..89427f7851b389cbbb54599eac953a82e21e6623 100644 (file)
@@ -23,7 +23,7 @@ use ops::Deref;
 use option::Option::{self, Some, None};
 use result::Result::{self, Ok, Err};
 use slice;
-use str;
+use str::{self, Utf8Error};
 use string::String;
 use vec::Vec;
 
@@ -151,6 +151,15 @@ pub struct CStr {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct NulError(usize, Vec<u8>);
 
+/// An error returned from `CString::into_string` to indicate that a UTF-8 error
+/// was encountered during the conversion.
+#[derive(Clone, PartialEq, Debug)]
+#[unstable(feature = "cstring_into", reason = "recently added", issue = "29157")]
+pub struct IntoStringError {
+    inner: CString,
+    error: Utf8Error,
+}
+
 impl CString {
     /// Creates a new C-compatible string from a container of bytes.
     ///
@@ -206,7 +215,7 @@ impl CString {
     /// Retakes ownership of a CString that was transferred to C.
     ///
     /// The only appropriate argument is a pointer obtained by calling
-    /// `into_ptr`. The length of the string will be recalculated
+    /// `into_raw`. The length of the string will be recalculated
     /// using the pointer.
     #[unstable(feature = "cstr_memory2", reason = "recently added",
                issue = "27769")]
@@ -245,16 +254,48 @@ impl CString {
     /// Transfers ownership of the string to a C caller.
     ///
     /// The pointer must be returned to Rust and reconstituted using
-    /// `from_ptr` to be properly deallocated. Specifically, one
+    /// `from_raw` to be properly deallocated. Specifically, one
     /// should *not* use the standard C `free` function to deallocate
     /// this string.
     ///
-    /// Failure to call `from_ptr` will lead to a memory leak.
+    /// Failure to call `from_raw` will lead to a memory leak.
     #[stable(feature = "cstr_memory", since = "1.4.0")]
     pub fn into_raw(self) -> *mut libc::c_char {
         Box::into_raw(self.inner) as *mut libc::c_char
     }
 
+    /// Converts the `CString` into a `String` if it contains valid Unicode data.
+    ///
+    /// On failure, ownership of the original `CString` is returned.
+    #[unstable(feature = "cstring_into", reason = "recently added", issue = "29157")]
+    pub fn into_string(self) -> Result<String, IntoStringError> {
+        String::from_utf8(self.into_bytes())
+            .map_err(|e| IntoStringError {
+                error: e.utf8_error(),
+                inner: unsafe { CString::from_vec_unchecked(e.into_bytes()) },
+            })
+    }
+
+    /// Returns the underlying byte buffer.
+    ///
+    /// The returned buffer does **not** contain the trailing nul separator and
+    /// it is guaranteed to not have any interior nul bytes.
+    #[unstable(feature = "cstring_into", reason = "recently added", issue = "29157")]
+    pub fn into_bytes(self) -> Vec<u8> {
+        // FIXME: Once this method becomes stable, add an `impl Into<Vec<u8>> for CString`
+        let mut vec = self.inner.into_vec();
+        let _nul = vec.pop();
+        debug_assert_eq!(_nul, Some(0u8));
+        vec
+    }
+
+    /// Equivalent to the `into_bytes` function except that the returned vector
+    /// includes the trailing nul byte.
+    #[unstable(feature = "cstring_into", reason = "recently added", issue = "29157")]
+    pub fn into_bytes_with_nul(self) -> Vec<u8> {
+        self.inner.into_vec()
+    }
+
     /// Returns the contents of this `CString` as a slice of bytes.
     ///
     /// The returned slice does **not** contain the trailing nul separator and
@@ -336,6 +377,35 @@ impl From<NulError> for io::Error {
     }
 }
 
+impl IntoStringError {
+    /// Consumes this error, returning original `CString` which generated the
+    /// error.
+    #[unstable(feature = "cstring_into", reason = "recently added", issue = "29157")]
+    pub fn into_cstring(self) -> CString {
+        self.inner
+    }
+
+    /// Access the underlying UTF-8 error that was the cause of this error.
+    #[unstable(feature = "cstring_into", reason = "recently added", issue = "29157")]
+    pub fn utf8_error(&self) -> Utf8Error {
+        self.error
+    }
+}
+
+#[unstable(feature = "cstring_into", reason = "recently added", issue = "29157")]
+impl Error for IntoStringError {
+    fn description(&self) -> &str {
+        Error::description(&self.error)
+    }
+}
+
+#[unstable(feature = "cstring_into", reason = "recently added", issue = "29157")]
+impl fmt::Display for IntoStringError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&self.error, f)
+    }
+}
+
 impl CStr {
     /// Casts a raw C string to a safe C string wrapper.
     ///
index dfe706e077366c609f2fb43c9ae95d3a12fa2ca3..bfd6ab52289b2f159190dfe9ee3470d65ac1ddde 100644 (file)
@@ -13,7 +13,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use self::c_str::{CString, CStr, NulError};
+pub use self::c_str::{CString, CStr, NulError, IntoStringError};
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::os_str::{OsString, OsStr};
index a3d509ba0f12dd83d2542fbf4f67be3b77305a80..6178f1bbb8e12d79b4ae8cf1354e664eed2c6544 100644 (file)
@@ -60,6 +60,7 @@ pub struct File {
 /// represents known metadata about a file such as its permissions, size,
 /// modification times, etc.
 #[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Clone)]
 pub struct Metadata(fs_imp::FileAttr);
 
 /// Iterator over the entries in a directory.
@@ -954,8 +955,21 @@ pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
 
 /// Returns the canonical form of a path with all intermediate components
 /// normalized and symbolic links resolved.
-#[unstable(feature = "fs_canonicalize", reason = "recently added API",
-           issue = "27706")]
+///
+/// This function may return an error in situations like where the path does not
+/// exist, a component in the path is not a directory, or an I/O error happens.
+///
+/// # Examples
+///
+/// ```
+/// use std::fs;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// let path = try!(fs::canonicalize("../a/../foo.txt"));
+/// # Ok(())
+/// # }
+/// ```
+#[stable(feature = "fs_canonicalize", since = "1.5.0")]
 pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
     fs_imp::canonicalize(path.as_ref())
 }
@@ -1157,11 +1171,12 @@ impl Iterator for WalkDir {
 }
 
 /// Utility methods for paths.
-#[unstable(feature = "path_ext",
+#[unstable(feature = "path_ext_deprecated",
            reason = "The precise set of methods exposed on this trait may \
                      change and some methods may be removed.  For stable code, \
                      see the std::fs::metadata function.",
            issue = "27725")]
+#[deprecated(since = "1.5.0", reason = "replaced with inherent methods")]
 pub trait PathExt {
     /// Gets information on the file, directory, etc at this path.
     ///
@@ -1214,6 +1229,7 @@ pub trait PathExt {
     fn is_dir(&self) -> bool;
 }
 
+#[allow(deprecated)]
 impl PathExt for Path {
     fn metadata(&self) -> io::Result<Metadata> { metadata(self) }
     fn symlink_metadata(&self) -> io::Result<Metadata> { symlink_metadata(self) }
@@ -2083,6 +2099,15 @@ mod tests {
         check!(fs::create_dir_all(&path.join("a/")));
     }
 
+    #[test]
+    fn canonicalize_works_simple() {
+        let tmpdir = tmpdir();
+        let tmpdir = fs::canonicalize(tmpdir.path()).unwrap();
+        let file = tmpdir.join("test");
+        File::create(&file).unwrap();
+        assert_eq!(fs::canonicalize(&file).unwrap(), file);
+    }
+
     #[test]
     #[cfg(not(windows))]
     fn realpath_works() {
@@ -2152,4 +2177,10 @@ mod tests {
             }
         }
     }
+
+    #[test]
+    fn read_dir_not_found() {
+        let res = fs::read_dir("/path/that/does/not/exist");
+        assert_eq!(res.err().unwrap().kind(), ErrorKind::NotFound);
+    }
 }
index 90bcbe7fe86587767e86c628dcaa3812b830fcbe..acab63315e4c4286b2af4ac04e583fd5c039fccc 100644 (file)
@@ -546,7 +546,7 @@ impl<W> IntoInnerError<W> {
     /// let stream = match stream.into_inner() {
     ///     Ok(s) => s,
     ///     Err(e) => {
-    ///         // Here, e is a IntoInnerError, let's re-examine the buffer:
+    ///         // Here, e is an IntoInnerError, let's re-examine the buffer:
     ///         let buffer = e.into_inner();
     ///
     ///         // do stuff to try to recover
index 9590f0b7aa72693eb6e4d21b99b3733cb01ad5c9..e4f00c4874e5fe82001f28701f2f92c571a270ff 100644 (file)
@@ -69,7 +69,7 @@ use slice;
 ///     use std::io::Cursor;
 ///     let mut buff = Cursor::new(vec![0; 15]);
 ///
-///     write_ten_bytes(&mut buff).unwrap();
+///     write_ten_bytes_at_end(&mut buff).unwrap();
 ///
 ///     assert_eq!(&buff.get_ref()[5..15], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
 /// }
@@ -192,67 +192,43 @@ impl<T> Cursor<T> {
     pub fn set_position(&mut self, pos: u64) { self.pos = pos; }
 }
 
-macro_rules! seek {
-    () => {
-        fn seek(&mut self, style: SeekFrom) -> io::Result<u64> {
-            let pos = match style {
-                SeekFrom::Start(n) => { self.pos = n; return Ok(n) }
-                SeekFrom::End(n) => self.inner.len() as i64 + n,
-                SeekFrom::Current(n) => self.pos as i64 + n,
-            };
-
-            if pos < 0 {
-                Err(Error::new(ErrorKind::InvalidInput,
-                               "invalid seek to a negative position"))
-            } else {
-                self.pos = pos as u64;
-                Ok(self.pos)
-            }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> io::Seek for Cursor<T> where T: AsRef<[u8]> {
+    fn seek(&mut self, style: SeekFrom) -> io::Result<u64> {
+        let pos = match style {
+            SeekFrom::Start(n) => { self.pos = n; return Ok(n) }
+            SeekFrom::End(n) => self.inner.as_ref().len() as i64 + n,
+            SeekFrom::Current(n) => self.pos as i64 + n,
+        };
+
+        if pos < 0 {
+            Err(Error::new(ErrorKind::InvalidInput,
+                           "invalid seek to a negative position"))
+        } else {
+            self.pos = pos as u64;
+            Ok(self.pos)
         }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> io::Seek for Cursor<&'a [u8]> { seek!(); }
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> io::Seek for Cursor<&'a mut [u8]> { seek!(); }
-#[stable(feature = "rust1", since = "1.0.0")]
-impl io::Seek for Cursor<Vec<u8>> { seek!(); }
-
-macro_rules! read {
-    () => {
-        fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-            let n = try!(Read::read(&mut try!(self.fill_buf()), buf));
-            self.pos += n as u64;
-            Ok(n)
-        }
+impl<T> Read for Cursor<T> where T: AsRef<[u8]> {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        let n = try!(Read::read(&mut try!(self.fill_buf()), buf));
+        self.pos += n as u64;
+        Ok(n)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> Read for Cursor<&'a [u8]> { read!(); }
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> Read for Cursor<&'a mut [u8]> { read!(); }
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Read for Cursor<Vec<u8>> { read!(); }
-
-macro_rules! buffer {
-    () => {
-        fn fill_buf(&mut self) -> io::Result<&[u8]> {
-            let amt = cmp::min(self.pos, self.inner.len() as u64);
-            Ok(&self.inner[(amt as usize)..])
-        }
-        fn consume(&mut self, amt: usize) { self.pos += amt as u64; }
+impl<T> BufRead for Cursor<T> where T: AsRef<[u8]> {
+    fn fill_buf(&mut self) -> io::Result<&[u8]> {
+        let amt = cmp::min(self.pos, self.inner.as_ref().len() as u64);
+        Ok(&self.inner.as_ref()[(amt as usize)..])
     }
+    fn consume(&mut self, amt: usize) { self.pos += amt as u64; }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> BufRead for Cursor<&'a [u8]> { buffer!(); }
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> BufRead for Cursor<&'a mut [u8]> { buffer!(); }
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> BufRead for Cursor<Vec<u8>> { buffer!(); }
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Write for Cursor<&'a mut [u8]> {
     fn write(&mut self, data: &[u8]) -> io::Result<usize> {
@@ -289,6 +265,16 @@ impl Write for Cursor<Vec<u8>> {
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
 
+#[stable(feature = "cursor_box_slice", since = "1.5.0")]
+impl Write for Cursor<Box<[u8]>> {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        let pos = cmp::min(self.pos, self.inner.len() as u64);
+        let amt = try!((&mut self.inner[(pos as usize)..]).write(buf));
+        self.pos += amt as u64;
+        Ok(amt)
+    }
+    fn flush(&mut self) -> io::Result<()> { Ok(()) }
+}
 
 #[cfg(test)]
 mod tests {
@@ -316,6 +302,24 @@ mod tests {
         assert_eq!(&writer.get_ref()[..], b);
     }
 
+    #[test]
+    fn test_box_slice_writer() {
+        let mut writer = Cursor::new(vec![0u8; 9].into_boxed_slice());
+        assert_eq!(writer.position(), 0);
+        assert_eq!(writer.write(&[0]).unwrap(), 1);
+        assert_eq!(writer.position(), 1);
+        assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
+        assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
+        assert_eq!(writer.position(), 8);
+        assert_eq!(writer.write(&[]).unwrap(), 0);
+        assert_eq!(writer.position(), 8);
+
+        assert_eq!(writer.write(&[8, 9]).unwrap(), 1);
+        assert_eq!(writer.write(&[10]).unwrap(), 0);
+        let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
+        assert_eq!(&**writer.get_ref(), b);
+    }
+
     #[test]
     fn test_buf_writer() {
         let mut buf = [0 as u8; 9];
@@ -397,6 +401,28 @@ mod tests {
         assert_eq!(reader.read(&mut buf).unwrap(), 0);
     }
 
+    #[test]
+    fn test_boxed_slice_reader() {
+        let mut reader = Cursor::new(vec!(0, 1, 2, 3, 4, 5, 6, 7).into_boxed_slice());
+        let mut buf = [];
+        assert_eq!(reader.read(&mut buf).unwrap(), 0);
+        assert_eq!(reader.position(), 0);
+        let mut buf = [0];
+        assert_eq!(reader.read(&mut buf).unwrap(), 1);
+        assert_eq!(reader.position(), 1);
+        let b: &[_] = &[0];
+        assert_eq!(buf, b);
+        let mut buf = [0; 4];
+        assert_eq!(reader.read(&mut buf).unwrap(), 4);
+        assert_eq!(reader.position(), 5);
+        let b: &[_] = &[1, 2, 3, 4];
+        assert_eq!(buf, b);
+        assert_eq!(reader.read(&mut buf).unwrap(), 3);
+        let b: &[_] = &[5, 6, 7];
+        assert_eq!(&buf[..3], b);
+        assert_eq!(reader.read(&mut buf).unwrap(), 0);
+    }
+
     #[test]
     fn read_to_end() {
         let mut reader = Cursor::new(vec!(0, 1, 2, 3, 4, 5, 6, 7));
@@ -483,6 +509,10 @@ mod tests {
         let mut r = Cursor::new(&mut buf[..]);
         assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
         assert_eq!(r.write(&[3]).unwrap(), 0);
+
+        let mut r = Cursor::new(vec![10].into_boxed_slice());
+        assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
+        assert_eq!(r.write(&[3]).unwrap(), 0);
     }
 
     #[test]
@@ -497,6 +527,9 @@ mod tests {
         let mut buf = [0];
         let mut r = Cursor::new(&mut buf[..]);
         assert!(r.seek(SeekFrom::End(-2)).is_err());
+
+        let mut r = Cursor::new(vec!(10).into_boxed_slice());
+        assert!(r.seek(SeekFrom::End(-2)).is_err());
     }
 
     #[test]
index 773f9ac6a12a7bc4aa34f4141deda13c08c0071d..6f18aad623574d5db6a7c0caae262a86ed2ce69b 100644 (file)
@@ -17,9 +17,8 @@ use option::Option::{self, Some, None};
 use result;
 use sys;
 
-/// A specialized [`Result`][result] type for I/O operations.
-///
-/// [result]: ../result/enum.Result.html
+/// A specialized [`Result`](../result/enum.Result.html) type for I/O
+/// operations.
 ///
 /// This type is broadly used across `std::io` for any operation which may
 /// produce an error.
index 79013000fe3b591c32ce1f65fd7632ddc191e5db..5b587dd921bb7e62e2213fbad35eeadab17cf33e 100644 (file)
@@ -238,7 +238,7 @@ mod tests {
 
         b.iter(|| {
             let mut rd = &buf[..];
-            for _ in (0 .. 8) {
+            for _ in 0..8 {
                 let _ = rd.read(&mut dst);
                 test::black_box(&dst);
             }
@@ -252,7 +252,7 @@ mod tests {
 
         b.iter(|| {
             let mut wr = &mut buf[..];
-            for _ in (0 .. 8) {
+            for _ in 0..8 {
                 let _ = wr.write_all(&src);
                 test::black_box(&wr);
             }
@@ -266,7 +266,7 @@ mod tests {
 
         b.iter(|| {
             let mut rd = &buf[..];
-            for _ in (0 .. 8) {
+            for _ in 0..8 {
                 let _ = rd.read(&mut dst);
                 test::black_box(&dst);
             }
@@ -280,7 +280,7 @@ mod tests {
 
         b.iter(|| {
             let mut wr = &mut buf[..];
-            for _ in (0 .. 8) {
+            for _ in 0..8 {
                 let _ = wr.write_all(&src);
                 test::black_box(&wr);
             }
index 54869807cacef4a99a447a4ed7359170dd8bf401..ebe50a6e2b8a2b83d5735701e8d869bfcc2d2cf2 100644 (file)
 //!
 //! # Read and Write
 //!
-//! Because they are traits, they're implemented by a number of other types,
-//! and you can implement them for your types too. As such, you'll see a
-//! few different types of I/O throughout the documentation in this module:
-//! `File`s, `TcpStream`s, and somtimes even `Vec<T>`s. For example, `Read`
-//! adds a `read()` method, which we can use on `File`s:
+//! Because they are traits, `Read` and `Write` are implemented by a number
+//! of other types, and you can implement them for your types too. As such,
+//! you'll see a few different types of I/O throughout the documentation in
+//! this module: `File`s, `TcpStream`s, and sometimes even `Vec<T>`s. For
+//! example, `Read` adds a `read()` method, which we can use on `File`s:
 //!
 //! ```
 //! use std::io;
 //! # }
 //! ```
 //!
-//! `BufWriter` doesn't add any new ways of writing, it just buffers every call
+//! `BufWriter` doesn't add any new ways of writing; it just buffers every call
 //! to [`write()`][write]:
 //!
 //! ```
 //! # }
 //! ```
 //!
-//! Of course, using `io::stdout()` directly is less comon than something like
+//! Of course, using `io::stdout()` directly is less common than something like
 //! `println!`.
 //!
 //! ## Iterator types
 //! The return type of `read_input()`, `io::Result<()>`, is a very common type
 //! for functions which don't have a 'real' return value, but do want to return
 //! errors if they happen. In this case, the only purpose of this function is
-//! to read the line and print it, so we use use `()`.
+//! to read the line and print it, so we use `()`.
 //!
 //! [result]: type.Result.html
 //! [try]: macro.try!.html
@@ -370,6 +370,13 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize>
 /// throughout `std::io` take and provide types which implement the `Read`
 /// trait.
 ///
+/// Please note that each call to `read` may involve a system call, and
+/// therefore, using something that implements [`BufRead`][bufread], such as
+/// [`BufReader`][bufreader], will be more efficient.
+///
+/// [bufread]: trait.BufRead.html
+/// [bufreader]: struct.BufReader.html
+///
 /// # Examples
 ///
 /// [`File`][file]s implement `Read`:
index db5c1da8a42274af24c1560bfa8e17b2b20696f9..f8fbe485c9b27d89071c7cc07c7e7177c64deadd 100644 (file)
@@ -21,4 +21,5 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 pub use super::{Read, Write, BufRead, Seek};
+#[allow(deprecated)]
 pub use fs::PathExt;
index c2110ef1d83b512bc22e12d45a7da25d5cd82352..31b881bebf05f9c0672821237be88af69e7bd19f 100644 (file)
@@ -146,7 +146,7 @@ pub struct Stdin {
     inner: Arc<Mutex<BufReader<Maybe<StdinRaw>>>>,
 }
 
-/// A locked reference to the `Stdin` handle.
+/// A locked reference to the `Stdin` handle.
 ///
 /// This handle implements both the `Read` and `BufRead` traits and is
 /// constructed via the `lock` method on `Stdin`.
@@ -323,7 +323,7 @@ pub struct Stdout {
     inner: Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>>,
 }
 
-/// A locked reference to the `Stdout` handle.
+/// A locked reference to the `Stdout` handle.
 ///
 /// This handle implements the `Write` trait and is constructed via the `lock`
 /// method on `Stdout`.
@@ -430,7 +430,7 @@ pub struct Stderr {
     inner: Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>>,
 }
 
-/// A locked reference to the `Stderr` handle.
+/// A locked reference to the `Stderr` handle.
 ///
 /// This handle implements the `Write` trait and is constructed via the `lock`
 /// method on `Stderr`.
index 774d13966bd6b4d2624b93996911c9bebcc32c90..93d1ce168b7e2e073afd763322f8ef955f528b52 100644 (file)
@@ -18,7 +18,7 @@
 //! language primitives](#primitives), [standard macros](#macros),
 //! [I/O](io/index.html) and [multithreading](thread/index.html), among
 //! [many other
-//! things](#what-is-in-the-standard-library-documentation?).
+//! things](#what-is-in-the-standard-library-documentation).
 //!
 //! `std` is available to all Rust crates by default, just as if each
 //! one contained an `extern crate std` import at the [crate
 //! not.
 //!
 //! Slices can only be handled through some kind of *pointer*, and as
-//! such come in many flavours such as:
+//! such come in many flavors such as:
 //!
 //! * `&[T]` - *shared slice*
 //! * `&mut [T]` - *mutable slice*
        test(no_crate_inject, attr(deny(warnings))),
        test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]
 
+// SNAP 1af31d4
+#![allow(unused_features)]
+// SNAP 1af31d4
+#![allow(unused_attributes)]
+
 #![feature(alloc)]
 #![feature(allow_internal_unstable)]
 #![feature(associated_consts)]
 #![feature(borrow_state)]
 #![feature(box_syntax)]
-#![feature(char_from_unchecked)]
+#![feature(cfg_target_vendor)]
 #![feature(char_internals)]
 #![feature(clone_from_slice)]
 #![feature(collections)]
 #![feature(heap_api)]
 #![feature(int_error_internals)]
 #![feature(into_cow)]
-#![feature(iter_order)]
 #![feature(lang_items)]
 #![feature(libc)]
 #![feature(linkage, thread_local, asm)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
 #![feature(unique)]
+#![feature(dropck_parametricity)]
 #![feature(unsafe_no_drop_flag, filling_drop)]
 #![feature(decode_utf16)]
 #![feature(unwind_attributes)]
 #![feature(vec_push_all)]
-#![feature(vec_resize)]
 #![feature(wrapping)]
 #![feature(zero_one)]
 #![cfg_attr(windows, feature(str_utf16))]
-#![cfg_attr(test, feature(float_from_str_radix, range_inclusive, float_extras, hash_default))]
-#![cfg_attr(test, feature(test, rustc_private, float_consts))]
+#![cfg_attr(test, feature(float_from_str_radix, range_inclusive, float_extras))]
+#![cfg_attr(test, feature(test, rustc_private))]
 #![cfg_attr(target_env = "msvc", feature(link_args))]
 
 // Don't link to std. We are std.
index a0c3f013f2b4e15280c58bd0957b57aedc00b743..a88ddb997f61d9aec982b5f35dd5791e7768e64e 100644 (file)
@@ -68,6 +68,10 @@ macro_rules! panic {
 /// necessary to use `io::stdout().flush()` to ensure the output is emitted
 /// immediately.
 ///
+/// # Panics
+///
+/// Panics if writing to `io::stdout()` fails.
+///
 /// # Examples
 ///
 /// ```
@@ -94,11 +98,15 @@ macro_rules! print {
     ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*)));
 }
 
-/// Macro for printing to the standard output.
+/// Macro for printing to the standard output, with a newline.
 ///
 /// Use the `format!` syntax to write data to the standard output.
 /// See `std::fmt` for more information.
 ///
+/// # Panics
+///
+/// Panics if writing to `io::stdout()` fails.
+///
 /// # Examples
 ///
 /// ```
index 09aea50cfbe9e00e896ced9161a1b2af0a54826f..827a3eb9bf600482f521dd569025efd96bffc285 100644 (file)
@@ -22,7 +22,7 @@ use libc;
 use sys_common::{AsInner, FromInner};
 use net::{hton, ntoh};
 
-/// An IP address, either a IPv4 or IPv6 address.
+/// An IP address, either an IPv4 or IPv6 address.
 #[unstable(feature = "ip_addr", reason = "recent addition", issue = "27801")]
 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
 pub enum IpAddr {
@@ -594,10 +594,18 @@ mod tests {
     fn test_from_str_socket_addr() {
         assert_eq!(Ok(sa4(Ipv4Addr::new(77, 88, 21, 11), 80)),
                    "77.88.21.11:80".parse());
+        assert_eq!(Ok(SocketAddrV4::new(Ipv4Addr::new(77, 88, 21, 11), 80)),
+                   "77.88.21.11:80".parse());
         assert_eq!(Ok(sa6(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), 53)),
                    "[2a02:6b8:0:1::1]:53".parse());
+        assert_eq!(Ok(SocketAddrV6::new(Ipv6Addr::new(0x2a02, 0x6b8, 0, 1,
+                                                      0, 0, 0, 1), 53, 0, 0)),
+                   "[2a02:6b8:0:1::1]:53".parse());
         assert_eq!(Ok(sa6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x7F00, 1), 22)),
                    "[::127.0.0.1]:22".parse());
+        assert_eq!(Ok(SocketAddrV6::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0,
+                                                      0x7F00, 1), 22, 0, 0)),
+                   "[::127.0.0.1]:22".parse());
 
         // without port
         let none: Option<SocketAddr> = "127.0.0.1".parse().ok();
index f0b35bbc38811d8251ca46476bd141241e6a1da0..1619dac78ca8ed1eb59469d6cf335d9d216977c9 100644 (file)
@@ -267,30 +267,42 @@ impl<'a> Parser<'a> {
         self.read_or(&mut [Box::new(ipv4_addr), Box::new(ipv6_addr)])
     }
 
-    fn read_socket_addr(&mut self) -> Option<SocketAddr> {
+    fn read_socket_addr_v4(&mut self) -> Option<SocketAddrV4> {
+        let ip_addr = |p: &mut Parser| p.read_ipv4_addr();
+        let colon = |p: &mut Parser| p.read_given_char(':');
+        let port = |p: &mut Parser| {
+            p.read_number(10, 5, 0x10000).map(|n| n as u16)
+        };
+
+        self.read_seq_3(ip_addr, colon, port).map(|t| {
+            let (ip, _, port): (Ipv4Addr, char, u16) = t;
+            SocketAddrV4::new(ip, port)
+        })
+    }
+
+    fn read_socket_addr_v6(&mut self) -> Option<SocketAddrV6> {
         let ip_addr = |p: &mut Parser| {
-            let ipv4_p = |p: &mut Parser| p.read_ip_addr();
-            let ipv6_p = |p: &mut Parser| {
-                let open_br = |p: &mut Parser| p.read_given_char('[');
-                let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
-                let clos_br = |p: &mut Parser| p.read_given_char(']');
-                p.read_seq_3::<char, Ipv6Addr, char, _, _, _>(open_br, ip_addr, clos_br)
-                        .map(|t| match t { (_, ip, _) => IpAddr::V6(ip) })
-            };
-            p.read_or(&mut [Box::new(ipv4_p), Box::new(ipv6_p)])
+            let open_br = |p: &mut Parser| p.read_given_char('[');
+            let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
+            let clos_br = |p: &mut Parser| p.read_given_char(']');
+            p.read_seq_3(open_br, ip_addr, clos_br).map(|t| t.1)
         };
         let colon = |p: &mut Parser| p.read_given_char(':');
-        let port  = |p: &mut Parser| p.read_number(10, 5, 0x10000).map(|n| n as u16);
+        let port = |p: &mut Parser| {
+            p.read_number(10, 5, 0x10000).map(|n| n as u16)
+        };
 
-        // host, colon, port
         self.read_seq_3(ip_addr, colon, port).map(|t| {
-            let (ip, _, port): (IpAddr, char, u16) = t;
-            match ip {
-                IpAddr::V4(ip) => SocketAddr::V4(SocketAddrV4::new(ip, port)),
-                IpAddr::V6(ip) => SocketAddr::V6(SocketAddrV6::new(ip, port, 0, 0)),
-            }
+            let (ip, _, port): (Ipv6Addr, char, u16) = t;
+            SocketAddrV6::new(ip, port, 0, 0)
         })
     }
+
+    fn read_socket_addr(&mut self) -> Option<SocketAddr> {
+        let v4 = |p: &mut Parser| p.read_socket_addr_v4().map(SocketAddr::V4);
+        let v6 = |p: &mut Parser| p.read_socket_addr_v6().map(SocketAddr::V6);
+        self.read_or(&mut [Box::new(v4), Box::new(v6)])
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -326,6 +338,28 @@ impl FromStr for Ipv6Addr {
     }
 }
 
+#[stable(feature = "socket_addr_from_str", since = "1.5.0")]
+impl FromStr for SocketAddrV4 {
+    type Err = AddrParseError;
+    fn from_str(s: &str) -> Result<SocketAddrV4, AddrParseError> {
+        match Parser::new(s).read_till_eof(|p| p.read_socket_addr_v4()) {
+            Some(s) => Ok(s),
+            None => Err(AddrParseError(())),
+        }
+    }
+}
+
+#[stable(feature = "socket_addr_from_str", since = "1.5.0")]
+impl FromStr for SocketAddrV6 {
+    type Err = AddrParseError;
+    fn from_str(s: &str) -> Result<SocketAddrV6, AddrParseError> {
+        match Parser::new(s).read_till_eof(|p| p.read_socket_addr_v6()) {
+            Some(s) => Ok(s),
+            None => Err(AddrParseError(())),
+        }
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl FromStr for SocketAddr {
     type Err = AddrParseError;
index 5c17ffb9c218af7a8e907fab73648f3006541cb3..93a056faf53f126554fabfd61cd81b8aa386bcec 100644 (file)
@@ -235,7 +235,7 @@ impl TcpListener {
     /// to this listener. The port allocated can be queried via the
     /// `socket_addr` function.
     ///
-    /// The address type can be any implementer of `ToSocketAddrs` trait. See
+    /// The address type can be any implementor of `ToSocketAddrs` trait. See
     /// its documentation for concrete examples.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
@@ -373,39 +373,28 @@ mod tests {
     }
 
     #[test]
-    fn connect_ip4_loopback() {
-        let addr = next_test_ip4();
-        let acceptor = t!(TcpListener::bind(&addr));
-
-        let _t = thread::spawn(move|| {
-            let mut stream = t!(TcpStream::connect(&("127.0.0.1", addr.port())));
-            t!(stream.write(&[44]));
-        });
-
-        let mut stream = t!(acceptor.accept()).0;
-        let mut buf = [0];
-        t!(stream.read(&mut buf));
-        assert!(buf[0] == 44);
-    }
-
-    #[test]
-    fn connect_ip6_loopback() {
-        let addr = next_test_ip6();
-        let acceptor = t!(TcpListener::bind(&addr));
+    fn connect_loopback() {
+        each_ip(&mut |addr| {
+            let acceptor = t!(TcpListener::bind(&addr));
 
-        let _t = thread::spawn(move|| {
-            let mut stream = t!(TcpStream::connect(&("::1", addr.port())));
-            t!(stream.write(&[66]));
-        });
+            let _t = thread::spawn(move|| {
+                let host = match addr {
+                    SocketAddr::V4(..) => "127.0.0.1",
+                    SocketAddr::V6(..) => "::1",
+                };
+                let mut stream = t!(TcpStream::connect(&(host, addr.port())));
+                t!(stream.write(&[66]));
+            });
 
-        let mut stream = t!(acceptor.accept()).0;
-        let mut buf = [0];
-        t!(stream.read(&mut buf));
-        assert!(buf[0] == 66);
+            let mut stream = t!(acceptor.accept()).0;
+            let mut buf = [0];
+            t!(stream.read(&mut buf));
+            assert!(buf[0] == 66);
+        })
     }
 
     #[test]
-    fn smoke_test_ip6() {
+    fn smoke_test() {
         each_ip(&mut |addr| {
             let acceptor = t!(TcpListener::bind(&addr));
 
@@ -425,7 +414,7 @@ mod tests {
     }
 
     #[test]
-    fn read_eof_ip4() {
+    fn read_eof() {
         each_ip(&mut |addr| {
             let acceptor = t!(TcpListener::bind(&addr));
 
@@ -470,7 +459,7 @@ mod tests {
     }
 
     #[test]
-    fn multiple_connect_serial_ip4() {
+    fn multiple_connect_serial() {
         each_ip(&mut |addr| {
             let max = 10;
             let acceptor = t!(TcpListener::bind(&addr));
@@ -527,7 +516,7 @@ mod tests {
     }
 
     #[test]
-    fn multiple_connect_interleaved_lazy_schedule_ip4() {
+    fn multiple_connect_interleaved_lazy_schedule() {
         const MAX: usize = 10;
         each_ip(&mut |addr| {
             let acceptor = t!(TcpListener::bind(&addr));
@@ -560,7 +549,7 @@ mod tests {
     }
 
     #[test]
-    fn socket_and_peer_name_ip4() {
+    fn socket_and_peer_name() {
         each_ip(&mut |addr| {
             let listener = t!(TcpListener::bind(&addr));
             let so_name = t!(listener.local_addr());
index c6d839d55a865d97c8e45285d4b263b1cc0564f0..9665fd722872fc54891d84a11e211fd194cc5741 100644 (file)
@@ -47,7 +47,9 @@ pub fn tsa<A: ToSocketAddrs>(a: A) -> Result<Vec<SocketAddr>, String> {
 // it is running in and assigns a port range based on it.
 fn base_port() -> u16 {
     let cwd = env::current_dir().unwrap();
-    let dirs = ["32-opt", "32-nopt", "64-opt", "64-nopt", "64-opt-vg",
+    let dirs = ["32-opt", "32-nopt",
+                "musl-64-opt", "cross-opt",
+                "64-opt", "64-nopt", "64-opt-vg", "64-debug-opt",
                 "all-opt", "snap3", "dist"];
     dirs.iter().enumerate().find(|&(_, dir)| {
         cwd.to_str().unwrap().contains(dir)
index 9e4d38e4615b1dc8d4da5f1888554435a5977ef8..0d3d15401fd54b893ac8042e9c893dfb55f4d7d2 100644 (file)
@@ -185,14 +185,13 @@ mod tests {
         }
     }
 
-    // FIXME #11530 this fails on android because tests are run as root
-    #[cfg_attr(any(windows, target_os = "android"), ignore)]
     #[test]
     fn bind_error() {
-        let addr = SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 1);
-        match UdpSocket::bind(&addr) {
+        match UdpSocket::bind("1.1.1.1:9999") {
             Ok(..) => panic!(),
-            Err(e) => assert_eq!(e.kind(), ErrorKind::PermissionDenied),
+            Err(e) => {
+                assert_eq!(e.kind(), ErrorKind::AddrNotAvailable)
+            }
         }
     }
 
index cad80c55140c793322e11099093c4b99e1dcdbb5..391ca16f6923aa7e46b7b1dfc73ff72a98d35c2b 100644 (file)
@@ -39,6 +39,7 @@ mod arch {
     pub type time_t = i32;
 
     #[repr(C)]
+    #[derive(Clone)]
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub struct stat {
         #[stable(feature = "raw_ext", since = "1.1.0")]
@@ -108,6 +109,7 @@ mod arch {
     pub type time_t = i64;
 
     #[repr(C)]
+    #[derive(Clone)]
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub struct stat {
         #[stable(feature = "raw_ext", since = "1.1.0")]
index 2427a4e409251914d7ed6762e55d1589ba1f0286..45e46b252a4abfc2cd2e386367685813edea72b5 100644 (file)
@@ -26,6 +26,7 @@ use os::unix::raw::{uid_t, gid_t};
 #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
 
 #[repr(C)]
+#[derive(Clone)]
 #[stable(feature = "raw_ext", since = "1.1.0")]
 pub struct stat {
     #[stable(feature = "raw_ext", since = "1.1.0")]
index 1c265fa62f19cb59ab36bb6c8bdd8a99987b6254..cb692b0662aad5e0bc63f5e47b251e98f55fa010 100644 (file)
@@ -26,6 +26,7 @@ use os::unix::raw::{uid_t, gid_t};
 #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
 
 #[repr(C)]
+#[derive(Clone)]
 #[stable(feature = "raw_ext", since = "1.1.0")]
 pub struct stat {
     #[stable(feature = "raw_ext", since = "1.1.0")]
index 65390aee0e1d002b5fc303a4df9580abd7623da6..2dc9a026153ac82301070349b74a0f2e351a9e3b 100644 (file)
@@ -33,6 +33,7 @@ mod arch {
     #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i32;
 
     #[repr(C)]
+    #[derive(Clone)]
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub struct stat {
         #[stable(feature = "raw_ext", since = "1.1.0")]
@@ -91,6 +92,7 @@ mod arch {
     #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
 
     #[repr(C)]
+    #[derive(Clone)]
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub struct stat {
         #[stable(feature = "raw_ext", since = "1.1.0")]
@@ -138,4 +140,3 @@ mod arch {
     }
 }
 
-
index a9803f50b7b67b7e390fa1078de3d78512868be0..aeb3e993a72f4fd8e856978ade5a27f3ecc3d23c 100644 (file)
@@ -25,6 +25,7 @@ use os::unix::raw::{uid_t, gid_t};
 #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = c_long;
 
 #[repr(C)]
+#[derive(Clone)]
 #[stable(feature = "raw_ext", since = "1.1.0")]
 pub struct stat {
     #[stable(feature = "raw_ext", since = "1.1.0")]
index 3275ce07b48ab04d6073e3e3c31ff8268e664ec6..d7abdef6b038f936006d2c3f5e38501098bae3d3 100644 (file)
@@ -35,6 +35,7 @@ mod arch {
     #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i32;
 
     #[repr(C)]
+    #[derive(Clone)]
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub struct stat {
         #[stable(feature = "raw_ext", since = "1.1.0")]
@@ -95,6 +96,7 @@ mod arch {
     #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i32;
 
     #[repr(C)]
+    #[derive(Clone)]
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub struct stat {
         #[stable(feature = "raw_ext", since = "1.1.0")]
@@ -154,6 +156,7 @@ mod arch {
     #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
 
     #[repr(C)]
+    #[derive(Clone)]
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub struct stat {
         #[stable(feature = "raw_ext", since = "1.1.0")]
@@ -211,6 +214,7 @@ mod arch {
     #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
 
     #[repr(C)]
+    #[derive(Clone)]
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub struct stat {
         #[stable(feature = "raw_ext", since = "1.1.0")]
index dbc1b8c726bfe70b00e25f2f5535fca7d31a7b5e..4abd6f2d4dea3507946dd77b0d30beb7374442b9 100644 (file)
@@ -25,6 +25,7 @@ use os::unix::raw::{uid_t, gid_t};
 #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = c_long;
 
 #[repr(C)]
+#[derive(Clone)]
 #[stable(feature = "raw_ext", since = "1.1.0")]
 pub struct stat {
     #[stable(feature = "raw_ext", since = "1.1.0")]
index d811b94c847b3d6947746039c165190c9f4794da..82898437687b9bb233c95cd87f9ff455203a1bb3 100644 (file)
@@ -34,6 +34,7 @@ mod arch {
     #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i32;
 
     #[repr(C)]
+    #[derive(Clone)]
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub struct stat {
         #[stable(feature = "raw_ext", since = "1.1.0")]
@@ -94,6 +95,7 @@ mod arch {
     #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i32;
 
     #[repr(C)]
+    #[derive(Clone)]
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub struct stat {
         #[stable(feature = "raw_ext", since = "1.1.0")]
@@ -153,6 +155,7 @@ mod arch {
     #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
 
     #[repr(C)]
+    #[derive(Clone)]
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub struct stat {
         #[stable(feature = "raw_ext", since = "1.1.0")]
@@ -210,6 +213,7 @@ mod arch {
     #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
 
     #[repr(C)]
+    #[derive(Clone)]
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub struct stat {
         #[stable(feature = "raw_ext", since = "1.1.0")]
index f9898dfbdb537eaedc2810790c644c18f7c794f4..882d08c66065e7b631c92189eaa6669cb869df57 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! NetBSD/OpenBSD-specific raw type definitions
+//! NetBSD-specific raw type definitions
 
 #![stable(feature = "raw_ext", since = "1.1.0")]
 
@@ -17,7 +17,7 @@ use os::unix::raw::{uid_t, gid_t};
 
 #[stable(feature = "raw_ext", since = "1.1.0")] pub type blkcnt_t = i64;
 #[stable(feature = "raw_ext", since = "1.1.0")] pub type blksize_t = u32;
-#[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = i32;
+#[stable(feature = "raw_ext", since = "1.1.0")] pub type dev_t = u64;
 #[stable(feature = "raw_ext", since = "1.1.0")] pub type fflags_t = u32;
 #[stable(feature = "raw_ext", since = "1.1.0")] pub type ino_t = u64;
 #[stable(feature = "raw_ext", since = "1.1.0")] pub type mode_t = u32;
@@ -26,6 +26,7 @@ use os::unix::raw::{uid_t, gid_t};
 #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
 
 #[repr(C)]
+#[derive(Clone)]
 #[stable(feature = "raw_ext", since = "1.1.0")]
 pub struct stat {
     #[stable(feature = "raw_ext", since = "1.1.0")]
@@ -55,6 +56,10 @@ pub struct stat {
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub st_ctime_nsec: c_long,
     #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_birthtime: time_t,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_birthtime_nsec: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
     pub st_size: off_t,
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub st_blocks: blkcnt_t,
@@ -64,8 +69,5 @@ pub struct stat {
     pub st_flags: fflags_t,
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub st_gen: u32,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_birthtime: time_t,
-    #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub st_birthtime_nsec: c_long,
+    st_spare: [u32; 2],
 }
index 79ca901ade7b50dd45263c271280affbb3714026..1cc0eedfcd050a6c6cf38aa7879b8014a797f6ef 100644 (file)
@@ -26,6 +26,7 @@ use os::unix::raw::{uid_t, gid_t};
 #[stable(feature = "raw_ext", since = "1.1.0")] pub type time_t = i64;
 
 #[repr(C)]
+#[derive(Clone)]
 #[stable(feature = "raw_ext", since = "1.1.0")]
 pub struct stat {
     #[stable(feature = "raw_ext", since = "1.1.0")]
index 9715939d644aa5b61ff258c9c8edf0623c9b82f2..2b2af350c992cc874737ccfe547e65ef9f7ffc2b 100644 (file)
@@ -12,11 +12,15 @@ use prelude::v1::*;
 use io::prelude::*;
 
 use any::Any;
+use cell::Cell;
 use cell::RefCell;
+use intrinsics;
 use sys::stdio::Stderr;
 use sys_common::backtrace;
 use sys_common::thread_info;
-use sys_common::unwind;
+use sys_common::util;
+
+thread_local! { pub static PANIC_COUNT: Cell<usize> = Cell::new(0) }
 
 thread_local! {
     pub static LOCAL_STDERR: RefCell<Option<Box<Write + Send>>> = {
@@ -24,7 +28,8 @@ thread_local! {
     }
 }
 
-pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) {
+fn log_panic(obj: &(Any+Send), file: &'static str, line: u32,
+             log_backtrace: bool) {
     let msg = match obj.downcast_ref::<&'static str>() {
         Some(s) => *s,
         None => match obj.downcast_ref::<String>() {
@@ -35,37 +40,59 @@ pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) {
     let mut err = Stderr::new().ok();
     let thread = thread_info::current_thread();
     let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
+
+    let write = |err: &mut ::io::Write| {
+        let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}",
+                         name, msg, file, line);
+        if log_backtrace {
+            let _ = backtrace::write(err);
+        }
+    };
+
     let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take());
     match (prev, err.as_mut()) {
         (Some(mut stderr), _) => {
-            // FIXME: what to do when the thread printing panics?
-            let _ = writeln!(stderr,
-                             "thread '{}' panicked at '{}', {}:{}\n",
-                             name, msg, file, line);
-            if backtrace::log_enabled() {
-                let _ = backtrace::write(&mut *stderr);
-            }
+            write(&mut *stderr);
             let mut s = Some(stderr);
             LOCAL_STDERR.with(|slot| {
                 *slot.borrow_mut() = s.take();
             });
         }
-        (None, Some(ref mut err)) => {
-            let _ = writeln!(err, "thread '{}' panicked at '{}', {}:{}",
-                             name, msg, file, line);
-            if backtrace::log_enabled() {
-                let _ = backtrace::write(err);
-            }
-        }
+        (None, Some(ref mut err)) => { write(err) }
         _ => {}
     }
+}
 
-    // If this is a double panic, make sure that we printed a backtrace
-    // for this panic.
-    match err {
-        Some(ref mut err) if unwind::panicking() && !backtrace::log_enabled() => {
-            let _ = backtrace::write(err);
-        }
-        _ => {}
+pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) {
+    let panics = PANIC_COUNT.with(|s| {
+        let count = s.get() + 1;
+        s.set(count);
+        count
+    });
+
+    // If this is the third nested call, on_panic triggered the last panic,
+    // otherwise the double-panic check would have aborted the process.
+    // Even if it is likely that on_panic was unable to log the backtrace,
+    // abort immediately to avoid infinite recursion, so that attaching a
+    // debugger provides a useable stacktrace.
+    if panics >= 3 {
+        util::dumb_print(format_args!("thread panicked while processing \
+                                       panic. aborting."));
+        unsafe { intrinsics::abort() }
+    }
+
+    // If this is a double panic, make sure that we print a backtrace
+    // for this panic. Otherwise only print it if logging is enabled.
+    let log_backtrace = panics >= 2 || backtrace::log_enabled();
+    log_panic(obj, file, line, log_backtrace);
+
+    if panics >= 2 {
+        // If a thread panics while it's already unwinding then we
+        // have limited options. Currently our preference is to
+        // just abort. In the future we may consider resuming
+        // unwinding or otherwise exiting the thread cleanly.
+        util::dumb_print(format_args!("thread panicked while panicking. \
+                                       aborting."));
+        unsafe { intrinsics::abort() }
     }
 }
index 8eb5d1f2726d644cd25100bba0a4aa2fbf41b6b1..fe12b671235a24d7f0294e5c97f853118a76a674 100644 (file)
 use ascii::*;
 use borrow::{Borrow, IntoCow, ToOwned, Cow};
 use cmp;
+use fmt;
+use fs;
+use io;
 use iter;
 use mem;
 use ops::{self, Deref};
 use string::String;
 use vec::Vec;
-use fmt;
 
 use ffi::{OsStr, OsString};
 
@@ -351,7 +353,6 @@ impl<'a> Prefix<'a> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn is_separator(c: char) -> bool {
-    use ascii::*;
     c.is_ascii() && is_sep_byte(c as u8)
 }
 
@@ -1292,7 +1293,7 @@ impl Path {
     /// use std::path::Path;
     ///
     /// let path_str = Path::new("foo.txt").to_str();
-    //// assert_eq!(path_str, Some("foo.txt"));
+    /// assert_eq!(path_str, Some("foo.txt"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn to_str(&self) -> Option<&str> {
@@ -1690,6 +1691,81 @@ impl Path {
     pub fn display(&self) -> Display {
         Display { path: self }
     }
+
+
+    /// Gets information on the file, directory, etc at this path.
+    ///
+    /// Consult the `fs::metadata` documentation for more info.
+    ///
+    /// This call preserves identical runtime/error semantics with
+    /// `fs::metadata`.
+    #[stable(feature = "path_ext", since = "1.5.0")]
+    pub fn metadata(&self) -> io::Result<fs::Metadata> {
+        fs::metadata(self)
+    }
+
+    /// Gets information on the file, directory, etc at this path.
+    ///
+    /// Consult the `fs::symlink_metadata` documentation for more info.
+    ///
+    /// This call preserves identical runtime/error semantics with
+    /// `fs::symlink_metadata`.
+    #[stable(feature = "path_ext", since = "1.5.0")]
+    pub fn symlink_metadata(&self) -> io::Result<fs::Metadata> {
+        fs::symlink_metadata(self)
+    }
+
+    /// Returns the canonical form of a path, normalizing all components and
+    /// eliminate all symlinks.
+    ///
+    /// This call preserves identical runtime/error semantics with
+    /// `fs::canonicalize`.
+    #[stable(feature = "path_ext", since = "1.5.0")]
+    pub fn canonicalize(&self) -> io::Result<PathBuf> {
+        fs::canonicalize(self)
+    }
+
+    /// Reads the symlink at this path.
+    ///
+    /// For more information see `fs::read_link`.
+    #[stable(feature = "path_ext", since = "1.5.0")]
+    pub fn read_link(&self) -> io::Result<PathBuf> {
+        fs::read_link(self)
+    }
+
+    /// Reads the directory at this path.
+    ///
+    /// For more information see `fs::read_dir`.
+    #[stable(feature = "path_ext", since = "1.5.0")]
+    pub fn read_dir(&self) -> io::Result<fs::ReadDir> {
+        fs::read_dir(self)
+    }
+
+    /// Boolean value indicator whether the underlying file exists on the local
+    /// filesystem. Returns false in exactly the cases where `fs::stat` fails.
+    #[stable(feature = "path_ext", since = "1.5.0")]
+    pub fn exists(&self) -> bool {
+        fs::metadata(self).is_ok()
+    }
+
+    /// Whether the underlying implementation (be it a file path, or something
+    /// else) points at a "regular file" on the FS. Will return false for paths
+    /// to non-existent locations or directories or other non-regular files
+    /// (named pipes, etc). Follows links when making this determination.
+    #[stable(feature = "path_ext", since = "1.5.0")]
+    pub fn is_file(&self) -> bool {
+        fs::metadata(self).map(|m| m.is_file()).unwrap_or(false)
+    }
+
+    /// Whether the underlying implementation (be it a file path, or something
+    /// else) is pointing at a directory in the underlying FS. Will return
+    /// false for paths to non-existent locations or if the item is not a
+    /// directory (eg files, named pipes, etc). Follows links when making this
+    /// determination.
+    #[stable(feature = "path_ext", since = "1.5.0")]
+    pub fn is_dir(&self) -> bool {
+        fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index 82578172802f66614810f9774574251d3e23e61a..08227cfb35322f00ead40d813010b853168bb206 100644 (file)
@@ -74,7 +74,7 @@
 //!     [`Eq`](../cmp/trait.Eq.html),
 //!     [`Ord`](../cmp/trait.Ord.html)
 //!   }.
-//!   The comparision traits, which implement the comparison operators
+//!   The comparison traits, which implement the comparison operators
 //!   and are often seen in trait bounds.
 //! * `std::convert::`{
 //!     [`AsRef`](../convert/trait.AsRef.html),
@@ -84,7 +84,7 @@
 //!   }.
 //!   Generic conversions, used by savvy API authors to create
 //!   overloaded methods.
-//! * `std::default::`[`Default`](../default/trait.Default).
+//! * `std::default::`[`Default`](../default/trait.Default.html).
 //!   Types that have default values.
 //! * `std::iter::`{
 //!     [`Iterator`](../iter/trait.Iterator.html),
index f2ae168e560bd1bfe07204d41084a2783fd6bb11..7d62d477a0a52acdd96e90d49e79dbf2dac4081e 100644 (file)
@@ -411,7 +411,7 @@ mod prim_isize { }
 
 #[doc(primitive = "usize")]
 //
-/// The pointer-sized signed integer type.
+/// The pointer-sized unsigned integer type.
 ///
 /// *[See also the `std::usize` module](usize/index.html).*
 ///
index 5f5d5a69003f29e1197dcf46f7953fd127dfe764..9d03022bb84e766b57caa326d14874ff04227d57 100644 (file)
@@ -75,7 +75,7 @@ impl IntoInner<imp::Process> for Child {
     fn into_inner(self) -> imp::Process { self.handle }
 }
 
-/// A handle to a child procesess's stdin
+/// A handle to a child process's stdin
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ChildStdin {
     inner: AnonPipe
@@ -100,7 +100,7 @@ impl IntoInner<AnonPipe> for ChildStdin {
     fn into_inner(self) -> AnonPipe { self.inner }
 }
 
-/// A handle to a child procesess's stdout
+/// A handle to a child process's stdout
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ChildStdout {
     inner: AnonPipe
@@ -121,7 +121,7 @@ impl IntoInner<AnonPipe> for ChildStdout {
     fn into_inner(self) -> AnonPipe { self.inner }
 }
 
-/// A handle to a child procesess's stderr
+/// A handle to a child process's stderr
 #[stable(feature = "process", since = "1.0.0")]
 pub struct ChildStderr {
     inner: AnonPipe
@@ -630,12 +630,15 @@ mod tests {
     fn signal_reported_right() {
         use os::unix::process::ExitStatusExt;
 
-        let p = Command::new("/bin/sh").arg("-c").arg("kill -9 $$").spawn();
-        assert!(p.is_ok());
-        let mut p = p.unwrap();
+        let mut p = Command::new("/bin/sh")
+                            .arg("-c").arg("read a")
+                            .stdin(Stdio::piped())
+                            .spawn().unwrap();
+        p.kill().unwrap();
         match p.wait().unwrap().signal() {
             Some(9) => {},
-            result => panic!("not terminated by signal 9 (instead, {:?})", result),
+            result => panic!("not terminated by signal 9 (instead, {:?})",
+                             result),
         }
     }
 
index 851726d91c6e873d46dca4969ab882113a53808a..1b32515e9f72ea76e57441f7ad3ce85bb6f94cf7 100644 (file)
@@ -21,12 +21,12 @@ use time::Duration;
 /// A type indicating whether a timed wait on a condition variable returned
 /// due to a time out or not.
 #[derive(Debug, PartialEq, Eq, Copy, Clone)]
-#[unstable(feature = "wait_timeout", reason = "newly added", issue = "27772")]
+#[stable(feature = "wait_timeout", since = "1.5.0")]
 pub struct WaitTimeoutResult(bool);
 
 impl WaitTimeoutResult {
     /// Returns whether the wait was known to have timed out.
-    #[unstable(feature = "wait_timeout", reason = "newly added", issue = "27772")]
+    #[stable(feature = "wait_timeout", since = "1.5.0")]
     pub fn timed_out(&self) -> bool {
         self.0
     }
@@ -189,8 +189,7 @@ impl Condvar {
     ///
     /// Like `wait`, the lock specified will be re-acquired when this function
     /// returns, regardless of whether the timeout elapsed or not.
-    #[unstable(feature = "wait_timeout", reason = "waiting for Duration",
-               issue = "27772")]
+    #[stable(feature = "wait_timeout", since = "1.5.0")]
     pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>,
                                dur: Duration)
                                -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> {
index 8c5cec969a6aa27af880a99e6563a1d8d0f58fe6..a0d0147296a969dd20c1180c6553315696304ffd 100644 (file)
@@ -427,7 +427,7 @@ impl<T> UnsafeFlavor<T> for Receiver<T> {
 /// use std::sync::mpsc::channel;
 /// use std::thread;
 ///
-/// // tx is is the sending half (tx for transmission), and rx is the receiving
+/// // tx is the sending half (tx for transmission), and rx is the receiving
 /// // half (rx for receiving).
 /// let (tx, rx) = channel();
 ///
index 846a97b547dc6d09e8909a7330c898516c26e2cc..c0cd6d127d285467f0ce2ba7805082840460828e 100644 (file)
@@ -13,7 +13,9 @@ use prelude::v1::*;
 use cell::UnsafeCell;
 use fmt;
 use marker;
+use mem;
 use ops::{Deref, DerefMut};
+use ptr;
 use sys_common::mutex as sys;
 use sys_common::poison::{self, TryLockError, TryLockResult, LockResult};
 
@@ -243,14 +245,61 @@ impl<T: ?Sized> Mutex<T> {
     pub fn is_poisoned(&self) -> bool {
         self.inner.poison.get()
     }
+
+    /// Consumes this mutex, returning the underlying data.
+    ///
+    /// # Failure
+    ///
+    /// If another user of this mutex panicked while holding the mutex, then
+    /// this call will return an error instead.
+    #[unstable(feature = "mutex_into_inner", reason = "recently added", issue = "28968")]
+    pub fn into_inner(self) -> LockResult<T> where T: Sized {
+        // We know statically that there are no outstanding references to
+        // `self` so there's no need to lock the inner StaticMutex.
+        //
+        // To get the inner value, we'd like to call `data.into_inner()`,
+        // but because `Mutex` impl-s `Drop`, we can't move out of it, so
+        // we'll have to destructure it manually instead.
+        unsafe {
+            // Like `let Mutex { inner, data } = self`.
+            let (inner, data) = {
+                let Mutex { ref inner, ref data } = self;
+                (ptr::read(inner), ptr::read(data))
+            };
+            mem::forget(self);
+            inner.lock.destroy();  // Keep in sync with the `Drop` impl.
+
+            poison::map_result(inner.poison.borrow(), |_| data.into_inner())
+        }
+    }
+
+    /// Returns a mutable reference to the underlying data.
+    ///
+    /// Since this call borrows the `Mutex` mutably, no actual locking needs to
+    /// take place---the mutable borrow statically guarantees no locks exist.
+    ///
+    /// # Failure
+    ///
+    /// If another user of this mutex panicked while holding the mutex, then
+    /// this call will return an error instead.
+    #[unstable(feature = "mutex_get_mut", reason = "recently added", issue = "28968")]
+    pub fn get_mut(&mut self) -> LockResult<&mut T> {
+        // We know statically that there are no other references to `self`, so
+        // there's no need to lock the inner StaticMutex.
+        let data = unsafe { &mut *self.data.get() };
+        poison::map_result(self.inner.poison.borrow(), |_| data )
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Drop for Mutex<T> {
+    #[unsafe_destructor_blind_to_params]
     fn drop(&mut self) {
         // This is actually safe b/c we know that there is no further usage of
         // this mutex (it's up to the user to arrange for a mutex to get
         // dropped, that's not our job)
+        //
+        // IMPORTANT: This code must be kept in sync with `Mutex::into_inner`.
         unsafe { self.inner.lock.destroy() }
     }
 }
@@ -371,10 +420,14 @@ mod tests {
 
     use sync::mpsc::channel;
     use sync::{Arc, Mutex, StaticMutex, Condvar};
+    use sync::atomic::{AtomicUsize, Ordering};
     use thread;
 
     struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
 
+    #[derive(Eq, PartialEq, Debug)]
+    struct NonCopy(i32);
+
     unsafe impl<T: Send> Send for Packet<T> {}
     unsafe impl<T> Sync for Packet<T> {}
 
@@ -435,6 +488,69 @@ mod tests {
         *m.try_lock().unwrap() = ();
     }
 
+    #[test]
+    fn test_into_inner() {
+        let m = Mutex::new(NonCopy(10));
+        assert_eq!(m.into_inner().unwrap(), NonCopy(10));
+    }
+
+    #[test]
+    fn test_into_inner_drop() {
+        struct Foo(Arc<AtomicUsize>);
+        impl Drop for Foo {
+            fn drop(&mut self) {
+                self.0.fetch_add(1, Ordering::SeqCst);
+            }
+        }
+        let num_drops = Arc::new(AtomicUsize::new(0));
+        let m = Mutex::new(Foo(num_drops.clone()));
+        assert_eq!(num_drops.load(Ordering::SeqCst), 0);
+        {
+            let _inner = m.into_inner().unwrap();
+            assert_eq!(num_drops.load(Ordering::SeqCst), 0);
+        }
+        assert_eq!(num_drops.load(Ordering::SeqCst), 1);
+    }
+
+    #[test]
+    fn test_into_inner_poison() {
+        let m = Arc::new(Mutex::new(NonCopy(10)));
+        let m2 = m.clone();
+        let _ = thread::spawn(move || {
+            let _lock = m2.lock().unwrap();
+            panic!("test panic in inner thread to poison mutex");
+        }).join();
+
+        assert!(m.is_poisoned());
+        match Arc::try_unwrap(m).unwrap().into_inner() {
+            Err(e) => assert_eq!(e.into_inner(), NonCopy(10)),
+            Ok(x) => panic!("into_inner of poisoned Mutex is Ok: {:?}", x),
+        }
+    }
+
+    #[test]
+    fn test_get_mut() {
+        let mut m = Mutex::new(NonCopy(10));
+        *m.get_mut().unwrap() = NonCopy(20);
+        assert_eq!(m.into_inner().unwrap(), NonCopy(20));
+    }
+
+    #[test]
+    fn test_get_mut_poison() {
+        let m = Arc::new(Mutex::new(NonCopy(10)));
+        let m2 = m.clone();
+        let _ = thread::spawn(move || {
+            let _lock = m2.lock().unwrap();
+            panic!("test panic in inner thread to poison mutex");
+        }).join();
+
+        assert!(m.is_poisoned());
+        match Arc::try_unwrap(m).unwrap().get_mut() {
+            Err(e) => assert_eq!(*e.into_inner(), NonCopy(10)),
+            Ok(x) => panic!("get_mut of poisoned Mutex is Ok: {:?}", x),
+        }
+    }
+
     #[test]
     fn test_mutex_arc_condvar() {
         let packet = Packet(Arc::new((Mutex::new(false), Condvar::new())));
@@ -536,16 +652,15 @@ mod tests {
         assert_eq!(*lock, 2);
     }
 
-    // FIXME(#25351) needs deeply nested coercions of DST structs.
-    // #[test]
-    // fn test_mutex_unsized() {
-    //     let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
-    //     {
-    //         let b = &mut *mutex.lock().unwrap();
-    //         b[0] = 4;
-    //         b[2] = 5;
-    //     }
-    //     let comp: &[i32] = &[4, 2, 5];
-    //     assert_eq!(&*mutex.lock().unwrap(), comp);
-    // }
+    #[test]
+    fn test_mutex_unsized() {
+        let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
+        {
+            let b = &mut *mutex.lock().unwrap();
+            b[0] = 4;
+            b[2] = 5;
+        }
+        let comp: &[i32] = &[4, 2, 5];
+        assert_eq!(&*mutex.lock().unwrap(), comp);
+    }
 }
index 7210328fad805b31fceddd2303d3f0baa1eded80..750c9e30c5c3716b37725b3a8c4c136186941b79 100644 (file)
@@ -13,7 +13,9 @@ use prelude::v1::*;
 use cell::UnsafeCell;
 use fmt;
 use marker;
+use mem;
 use ops::{Deref, DerefMut};
+use ptr;
 use sys_common::poison::{self, LockResult, TryLockError, TryLockResult};
 use sys_common::rwlock as sys;
 
@@ -260,11 +262,61 @@ impl<T: ?Sized> RwLock<T> {
     pub fn is_poisoned(&self) -> bool {
         self.inner.poison.get()
     }
+
+    /// Consumes this `RwLock`, returning the underlying data.
+    ///
+    /// # Failure
+    ///
+    /// This function will return an error if the RwLock is poisoned. An RwLock
+    /// is poisoned whenever a writer panics while holding an exclusive lock. An
+    /// error will only be returned if the lock would have otherwise been
+    /// acquired.
+    #[unstable(feature = "rwlock_into_inner", reason = "recently added", issue = "28968")]
+    pub fn into_inner(self) -> LockResult<T> where T: Sized {
+        // We know statically that there are no outstanding references to
+        // `self` so there's no need to lock the inner StaticRwLock.
+        //
+        // To get the inner value, we'd like to call `data.into_inner()`,
+        // but because `RwLock` impl-s `Drop`, we can't move out of it, so
+        // we'll have to destructure it manually instead.
+        unsafe {
+            // Like `let RwLock { inner, data } = self`.
+            let (inner, data) = {
+                let RwLock { ref inner, ref data } = self;
+                (ptr::read(inner), ptr::read(data))
+            };
+            mem::forget(self);
+            inner.lock.destroy();  // Keep in sync with the `Drop` impl.
+
+            poison::map_result(inner.poison.borrow(), |_| data.into_inner())
+        }
+    }
+
+    /// Returns a mutable reference to the underlying data.
+    ///
+    /// Since this call borrows the `RwLock` mutably, no actual locking needs to
+    /// take place---the mutable borrow statically guarantees no locks exist.
+    ///
+    /// # Failure
+    ///
+    /// This function will return an error if the RwLock is poisoned. An RwLock
+    /// is poisoned whenever a writer panics while holding an exclusive lock. An
+    /// error will only be returned if the lock would have otherwise been
+    /// acquired.
+    #[unstable(feature = "rwlock_get_mut", reason = "recently added", issue = "28968")]
+    pub fn get_mut(&mut self) -> LockResult<&mut T> {
+        // We know statically that there are no other references to `self`, so
+        // there's no need to lock the inner StaticRwLock.
+        let data = unsafe { &mut *self.data.get() };
+        poison::map_result(self.inner.poison.borrow(), |_| data )
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Drop for RwLock<T> {
+    #[unsafe_destructor_blind_to_params]
     fn drop(&mut self) {
+        // IMPORTANT: This code needs to be kept in sync with `RwLock::into_inner`.
         unsafe { self.inner.lock.destroy() }
     }
 }
@@ -426,6 +478,10 @@ mod tests {
     use sync::mpsc::channel;
     use thread;
     use sync::{Arc, RwLock, StaticRwLock, TryLockError};
+    use sync::atomic::{AtomicUsize, Ordering};
+
+    #[derive(Eq, PartialEq, Debug)]
+    struct NonCopy(i32);
 
     #[test]
     fn smoke() {
@@ -578,18 +634,17 @@ mod tests {
         assert_eq!(*lock, 2);
     }
 
-    // FIXME(#25351) needs deeply nested coercions of DST structs.
-    // #[test]
-    // fn test_rwlock_unsized() {
-    //     let rw: &RwLock<[i32]> = &RwLock::new([1, 2, 3]);
-    //     {
-    //         let b = &mut *rw.write().unwrap();
-    //         b[0] = 4;
-    //         b[2] = 5;
-    //     }
-    //     let comp: &[i32] = &[4, 2, 5];
-    //     assert_eq!(&*rw.read().unwrap(), comp);
-    // }
+    #[test]
+    fn test_rwlock_unsized() {
+        let rw: &RwLock<[i32]> = &RwLock::new([1, 2, 3]);
+        {
+            let b = &mut *rw.write().unwrap();
+            b[0] = 4;
+            b[2] = 5;
+        }
+        let comp: &[i32] = &[4, 2, 5];
+        assert_eq!(&*rw.read().unwrap(), comp);
+    }
 
     #[test]
     fn test_rwlock_try_write() {
@@ -607,4 +662,67 @@ mod tests {
 
         drop(read_guard);
     }
+
+    #[test]
+    fn test_into_inner() {
+        let m = RwLock::new(NonCopy(10));
+        assert_eq!(m.into_inner().unwrap(), NonCopy(10));
+    }
+
+    #[test]
+    fn test_into_inner_drop() {
+        struct Foo(Arc<AtomicUsize>);
+        impl Drop for Foo {
+            fn drop(&mut self) {
+                self.0.fetch_add(1, Ordering::SeqCst);
+            }
+        }
+        let num_drops = Arc::new(AtomicUsize::new(0));
+        let m = RwLock::new(Foo(num_drops.clone()));
+        assert_eq!(num_drops.load(Ordering::SeqCst), 0);
+        {
+            let _inner = m.into_inner().unwrap();
+            assert_eq!(num_drops.load(Ordering::SeqCst), 0);
+        }
+        assert_eq!(num_drops.load(Ordering::SeqCst), 1);
+    }
+
+    #[test]
+    fn test_into_inner_poison() {
+        let m = Arc::new(RwLock::new(NonCopy(10)));
+        let m2 = m.clone();
+        let _ = thread::spawn(move || {
+            let _lock = m2.write().unwrap();
+            panic!("test panic in inner thread to poison RwLock");
+        }).join();
+
+        assert!(m.is_poisoned());
+        match Arc::try_unwrap(m).unwrap().into_inner() {
+            Err(e) => assert_eq!(e.into_inner(), NonCopy(10)),
+            Ok(x) => panic!("into_inner of poisoned RwLock is Ok: {:?}", x),
+        }
+    }
+
+    #[test]
+    fn test_get_mut() {
+        let mut m = RwLock::new(NonCopy(10));
+        *m.get_mut().unwrap() = NonCopy(20);
+        assert_eq!(m.into_inner().unwrap(), NonCopy(20));
+    }
+
+    #[test]
+    fn test_get_mut_poison() {
+        let m = Arc::new(RwLock::new(NonCopy(10)));
+        let m2 = m.clone();
+        let _ = thread::spawn(move || {
+            let _lock = m2.write().unwrap();
+            panic!("test panic in inner thread to poison RwLock");
+        }).join();
+
+        assert!(m.is_poisoned());
+        match Arc::try_unwrap(m).unwrap().get_mut() {
+            Err(e) => assert_eq!(*e.into_inner(), NonCopy(10)),
+            Ok(x) => panic!("get_mut of poisoned RwLock is Ok: {:?}", x),
+        }
+    }
 }
index c6bffb0f733eeab4223110db1017b4cd39f51921..da7ebbf4ed39f57b0f67b44a0307c9f74f2c3575 100644 (file)
@@ -108,10 +108,18 @@ extern {}
 #[link(name = "unwind", kind = "static")]
 extern {}
 
-#[cfg(any(target_os = "android", target_os = "netbsd", target_os = "openbsd"))]
+#[cfg(any(target_os = "android", target_os = "openbsd"))]
 #[link(name = "gcc")]
 extern {}
 
+#[cfg(all(target_os = "netbsd", not(target_vendor = "rumprun")))]
+#[link(name = "gcc")]
+extern {}
+
+#[cfg(all(target_os = "netbsd", target_vendor = "rumprun"))]
+#[link(name = "unwind")]
+extern {}
+
 #[cfg(target_os = "dragonfly")]
 #[link(name = "gcc_pic")]
 extern {}
index 738681c3cfed7469023d2e39cb74d44743c57ab4..d87ab56d4e17729c0af9cabc8edebd56191106b8 100644 (file)
@@ -64,9 +64,8 @@ use prelude::v1::*;
 
 use any::Any;
 use boxed;
-use cell::Cell;
 use cmp;
-use panicking;
+use panicking::{self,PANIC_COUNT};
 use fmt;
 use intrinsics;
 use mem;
@@ -82,8 +81,18 @@ use sys_common::mutex::Mutex;
 #[path = "seh.rs"] #[doc(hidden)]
 pub mod imp;
 
+// stage0: i686-pc-windows-gnu
+#[cfg(all(stage0, windows, target_arch = "x86_64", target_env = "gnu"))]
+#[path = "seh64_gnu.rs"] #[doc(hidden)]
+pub mod imp;
+
+// stage0: x86_64-pc-windows-msvc
+#[cfg(all(stage0, windows, target_arch = "x86_64", target_env = "msvc"))]
+#[path = "seh.rs"] #[doc(hidden)]
+pub mod imp;
+
 // x86_64-pc-windows-*
-#[cfg(all(windows, target_arch = "x86_64"))]
+#[cfg(all(not(stage0), windows, target_arch = "x86_64"))]
 #[path = "seh64_gnu.rs"] #[doc(hidden)]
 pub mod imp;
 
@@ -92,25 +101,6 @@ pub mod imp;
 #[path = "gcc.rs"] #[doc(hidden)]
 pub mod imp;
 
-pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: u32);
-
-// Variables used for invoking callbacks when a thread starts to unwind.
-//
-// For more information, see below.
-const MAX_CALLBACKS: usize = 16;
-static CALLBACKS: [atomic::AtomicUsize; MAX_CALLBACKS] =
-        [atomic::AtomicUsize::new(0), atomic::AtomicUsize::new(0),
-         atomic::AtomicUsize::new(0), atomic::AtomicUsize::new(0),
-         atomic::AtomicUsize::new(0), atomic::AtomicUsize::new(0),
-         atomic::AtomicUsize::new(0), atomic::AtomicUsize::new(0),
-         atomic::AtomicUsize::new(0), atomic::AtomicUsize::new(0),
-         atomic::AtomicUsize::new(0), atomic::AtomicUsize::new(0),
-         atomic::AtomicUsize::new(0), atomic::AtomicUsize::new(0),
-         atomic::AtomicUsize::new(0), atomic::AtomicUsize::new(0)];
-static CALLBACK_CNT: atomic::AtomicUsize = atomic::AtomicUsize::new(0);
-
-thread_local! { static PANICKING: Cell<bool> = Cell::new(false) }
-
 /// Invoke a closure, capturing the cause of panic if one occurs.
 ///
 /// This function will return `Ok(())` if the closure did not panic, and will
@@ -148,15 +138,17 @@ pub unsafe fn try<F: FnOnce()>(f: F) -> Result<(), Box<Any + Send>> {
     // care of exposing correctly.
     unsafe fn inner_try(f: fn(*mut u8), data: *mut u8)
                         -> Result<(), Box<Any + Send>> {
-        let prev = PANICKING.with(|s| s.get());
-        PANICKING.with(|s| s.set(false));
-        let ep = intrinsics::try(f, data);
-        PANICKING.with(|s| s.set(prev));
-        if ep.is_null() {
-            Ok(())
-        } else {
-            Err(imp::cleanup(ep))
-        }
+        PANIC_COUNT.with(|s| {
+            let prev = s.get();
+            s.set(0);
+            let ep = intrinsics::try(f, data);
+            s.set(prev);
+            if ep.is_null() {
+                Ok(())
+            } else {
+                Err(imp::cleanup(ep))
+            }
+        })
     }
 
     fn try_fn<F: FnOnce()>(opt_closure: *mut u8) {
@@ -176,7 +168,7 @@ pub unsafe fn try<F: FnOnce()>(f: F) -> Result<(), Box<Any + Send>> {
 
 /// Determines whether the current thread is unwinding because of panic.
 pub fn panicking() -> bool {
-    PANICKING.with(|s| s.get())
+    PANIC_COUNT.with(|s| s.get() != 0)
 }
 
 // An uninlined, unmangled function upon which to slap yer breakpoints
@@ -244,83 +236,11 @@ pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, u32)) -> !
 #[inline(never)] #[cold] // this is the slow path, please never inline this
 fn begin_unwind_inner(msg: Box<Any + Send>,
                       file_line: &(&'static str, u32)) -> ! {
-    // Make sure the default failure handler is registered before we look at the
-    // callbacks. We also use a raw sys-based mutex here instead of a
-    // `std::sync` one as accessing TLS can cause weird recursive problems (and
-    // we don't need poison checking).
-    unsafe {
-        static LOCK: Mutex = Mutex::new();
-        static mut INIT: bool = false;
-        LOCK.lock();
-        if !INIT {
-            register(panicking::on_panic);
-            INIT = true;
-        }
-        LOCK.unlock();
-    }
+    let (file, line) = *file_line;
 
-    // First, invoke call the user-defined callbacks triggered on thread panic.
-    //
-    // By the time that we see a callback has been registered (by reading
-    // MAX_CALLBACKS), the actual callback itself may have not been stored yet,
-    // so we just chalk it up to a race condition and move on to the next
-    // callback. Additionally, CALLBACK_CNT may briefly be higher than
-    // MAX_CALLBACKS, so we're sure to clamp it as necessary.
-    let callbacks = {
-        let amt = CALLBACK_CNT.load(Ordering::SeqCst);
-        &CALLBACKS[..cmp::min(amt, MAX_CALLBACKS)]
-    };
-    for cb in callbacks {
-        match cb.load(Ordering::SeqCst) {
-            0 => {}
-            n => {
-                let f: Callback = unsafe { mem::transmute(n) };
-                let (file, line) = *file_line;
-                f(&*msg, file, line);
-            }
-        }
-    };
+    // First, invoke the default panic handler.
+    panicking::on_panic(&*msg, file, line);
 
-    // Now that we've run all the necessary unwind callbacks, we actually
-    // perform the unwinding.
-    if panicking() {
-        // If a thread panics while it's already unwinding then we
-        // have limited options. Currently our preference is to
-        // just abort. In the future we may consider resuming
-        // unwinding or otherwise exiting the thread cleanly.
-        super::util::dumb_print(format_args!("thread panicked while panicking. \
-                                              aborting."));
-        unsafe { intrinsics::abort() }
-    }
-    PANICKING.with(|s| s.set(true));
+    // Finally, perform the unwinding.
     rust_panic(msg);
 }
-
-/// Register a callback to be invoked when a thread unwinds.
-///
-/// This is an unsafe and experimental API which allows for an arbitrary
-/// callback to be invoked when a thread panics. This callback is invoked on both
-/// the initial unwinding and a double unwinding if one occurs. Additionally,
-/// the local `Thread` will be in place for the duration of the callback, and
-/// the callback must ensure that it remains in place once the callback returns.
-///
-/// Only a limited number of callbacks can be registered, and this function
-/// returns whether the callback was successfully registered or not. It is not
-/// currently possible to unregister a callback once it has been registered.
-pub unsafe fn register(f: Callback) -> bool {
-    match CALLBACK_CNT.fetch_add(1, Ordering::SeqCst) {
-        // The invocation code has knowledge of this window where the count has
-        // been incremented, but the callback has not been stored. We're
-        // guaranteed that the slot we're storing into is 0.
-        n if n < MAX_CALLBACKS => {
-            let prev = CALLBACKS[n].swap(mem::transmute(f), Ordering::SeqCst);
-            rtassert!(prev == 0);
-            true
-        }
-        // If we accidentally bumped the count too high, pull it back.
-        _ => {
-            CALLBACK_CNT.store(MAX_CALLBACKS, Ordering::SeqCst);
-            false
-        }
-    }
-}
index 633e7d78a9aebfbd9d62a8b7ee6de8d3cb377ea1..271aba680a2d66ee1979816cd556b84b4a555596 100644 (file)
@@ -31,7 +31,6 @@ use core::str::next_code_point;
 use ascii::*;
 use borrow::Cow;
 use char;
-use cmp;
 use fmt;
 use hash::{Hash, Hasher};
 use iter::FromIterator;
@@ -147,13 +146,13 @@ impl fmt::Debug for Wtf8Buf {
 }
 
 impl Wtf8Buf {
-    /// Creates an new, empty WTF-8 string.
+    /// Creates a new, empty WTF-8 string.
     #[inline]
     pub fn new() -> Wtf8Buf {
         Wtf8Buf { bytes: Vec::new() }
     }
 
-    /// Creates an new, empty WTF-8 string with pre-allocated capacity for `n` bytes.
+    /// Creates a new, empty WTF-8 string with pre-allocated capacity for `n` bytes.
     #[inline]
     pub fn with_capacity(n: usize) -> Wtf8Buf {
         Wtf8Buf { bytes: Vec::with_capacity(n) }
@@ -375,6 +374,7 @@ impl Extend<CodePoint> for Wtf8Buf {
 ///
 /// Similar to `&str`, but can additionally contain surrogate code points
 /// if they’re not in a surrogate pair.
+#[derive(Eq, Ord, PartialEq, PartialOrd)]
 pub struct Wtf8 {
     bytes: [u8]
 }
@@ -383,36 +383,6 @@ impl AsInner<[u8]> for Wtf8 {
     fn as_inner(&self) -> &[u8] { &self.bytes }
 }
 
-// FIXME: https://github.com/rust-lang/rust/issues/18805
-impl PartialEq for Wtf8 {
-    fn eq(&self, other: &Wtf8) -> bool { self.bytes.eq(&other.bytes) }
-}
-
-// FIXME: https://github.com/rust-lang/rust/issues/18805
-impl Eq for Wtf8 {}
-
-// FIXME: https://github.com/rust-lang/rust/issues/18738
-impl PartialOrd for Wtf8 {
-    #[inline]
-    fn partial_cmp(&self, other: &Wtf8) -> Option<cmp::Ordering> {
-        self.bytes.partial_cmp(&other.bytes)
-    }
-    #[inline]
-    fn lt(&self, other: &Wtf8) -> bool { self.bytes.lt(&other.bytes) }
-    #[inline]
-    fn le(&self, other: &Wtf8) -> bool { self.bytes.le(&other.bytes) }
-    #[inline]
-    fn gt(&self, other: &Wtf8) -> bool { self.bytes.gt(&other.bytes) }
-    #[inline]
-    fn ge(&self, other: &Wtf8) -> bool { self.bytes.ge(&other.bytes) }
-}
-
-// FIXME: https://github.com/rust-lang/rust/issues/18738
-impl Ord for Wtf8 {
-    #[inline]
-    fn cmp(&self, other: &Wtf8) -> cmp::Ordering { self.bytes.cmp(&other.bytes) }
-}
-
 /// Format the slice with double quotes,
 /// and surrogates as `\u` followed by four hexadecimal digits.
 /// Example: `"a\u{D800}"` for a slice with code points [U+0061, U+D800]
@@ -1049,7 +1019,7 @@ mod tests {
     fn wtf8buf_from_iterator() {
         fn f(values: &[u32]) -> Wtf8Buf {
             values.iter().map(|&c| CodePoint::from_u32(c).unwrap()).collect::<Wtf8Buf>()
-        };
+        }
         assert_eq!(f(&[0x61, 0xE9, 0x20, 0x1F4A9]).bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
 
         assert_eq!(f(&[0xD83D, 0xDCA9]).bytes, b"\xF0\x9F\x92\xA9");  // Magic!
@@ -1068,7 +1038,7 @@ mod tests {
             let mut string = initial.iter().map(c).collect::<Wtf8Buf>();
             string.extend(extended.iter().map(c));
             string
-        };
+        }
 
         assert_eq!(e(&[0x61, 0xE9], &[0x20, 0x1F4A9]).bytes,
                    b"a\xC3\xA9 \xF0\x9F\x92\xA9");
index eeecf7f50f79a52fa522e7a8a173a0a0dfda76fa..051b3d8897d90c6c8413d8712aa413c99d80b541 100644 (file)
@@ -61,9 +61,10 @@ pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 70;
           target_os = "dragonfly"))]
 pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 71;
 #[cfg(any(target_os = "bitrig",
-          target_os = "netbsd",
           target_os = "openbsd"))]
 pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 101;
+#[cfg(target_os = "netbsd")]
+pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 48;
 #[cfg(target_os = "android")]
 pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 0x0048;
 
@@ -131,26 +132,31 @@ extern {
 
     pub fn raise(signum: libc::c_int) -> libc::c_int;
 
+    #[cfg_attr(target_os = "netbsd", link_name = "__sigaction14")]
     pub fn sigaction(signum: libc::c_int,
                      act: *const sigaction,
                      oldact: *mut sigaction) -> libc::c_int;
 
+    #[cfg_attr(target_os = "netbsd", link_name = "__sigaltstack14")]
     pub fn sigaltstack(ss: *const sigaltstack,
                        oss: *mut sigaltstack) -> libc::c_int;
 
     #[cfg(not(target_os = "android"))]
+    #[cfg_attr(target_os = "netbsd", link_name = "__sigemptyset14")]
     pub fn sigemptyset(set: *mut sigset_t) -> libc::c_int;
 
     pub fn pthread_sigmask(how: libc::c_int, set: *const sigset_t,
                            oldset: *mut sigset_t) -> libc::c_int;
 
     #[cfg(not(target_os = "ios"))]
+    #[cfg_attr(target_os = "netbsd", link_name = "__getpwuid_r50")]
     pub fn getpwuid_r(uid: libc::uid_t,
                       pwd: *mut passwd,
                       buf: *mut libc::c_char,
                       buflen: libc::size_t,
                       result: *mut *mut passwd) -> libc::c_int;
 
+    #[cfg_attr(target_os = "netbsd", link_name = "__utimes50")]
     pub fn utimes(filename: *const libc::c_char,
                   times: *const libc::timeval) -> libc::c_int;
     pub fn gai_strerror(errcode: libc::c_int) -> *const libc::c_char;
@@ -347,12 +353,12 @@ mod signal_os {
     #[cfg(any(target_os = "macos",
               target_os = "ios"))]
     pub type sigset_t = u32;
-    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+    #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "netbsd"))]
     #[repr(C)]
     pub struct sigset_t {
         bits: [u32; 4],
     }
-    #[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))]
+    #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
     pub type sigset_t = libc::c_uint;
 
     // This structure has more fields, but we're not all that interested in
index 46ab83199f0f72264f33e1fa23db4bb38fd1162f..5ef37ae51c994661f16ecca021b180892ea18b94 100644 (file)
@@ -178,21 +178,23 @@ impl MetadataExt for fs::Metadata {
 }
 
 /// Add special unix types (block/char device, fifo and socket)
-#[unstable(feature = "file_type_ext", reason = "recently added API",
-           issue = "27796")]
+#[stable(feature = "file_type_ext", since = "1.5.0")]
 pub trait FileTypeExt {
     /// Returns whether this file type is a block device.
+    #[stable(feature = "file_type_ext", since = "1.5.0")]
     fn is_block_device(&self) -> bool;
     /// Returns whether this file type is a char device.
+    #[stable(feature = "file_type_ext", since = "1.5.0")]
     fn is_char_device(&self) -> bool;
     /// Returns whether this file type is a fifo.
+    #[stable(feature = "file_type_ext", since = "1.5.0")]
     fn is_fifo(&self) -> bool;
     /// Returns whether this file type is a socket.
+    #[stable(feature = "file_type_ext", since = "1.5.0")]
     fn is_socket(&self) -> bool;
 }
 
-#[unstable(feature = "file_type_ext", reason = "recently added API",
-           issue = "27796")]
+#[stable(feature = "file_type_ext", since = "1.5.0")]
 impl FileTypeExt for fs::FileType {
     fn is_block_device(&self) -> bool { self.as_inner().is(libc::S_IFBLK) }
     fn is_char_device(&self) -> bool { self.as_inner().is(libc::S_IFCHR) }
index 81980ea25fb56c75e9c021b0623a963b91dc6a33..dcfa376c81e3b6e461dd3a0040a2ba1ab97134e1 100644 (file)
@@ -39,7 +39,7 @@ pub trait CommandExt {
     /// This is not enough to create a daemon process. The *init* process should
     /// be the child reaper of a daemon. This can be achieved if the parent
     /// process exit. Moreover, a daemon should not have a controlling terminal.
-    /// To acheive this, a session leader (the child) must spawn another process
+    /// To achieve this, a session leader (the child) must spawn another process
     /// (the daemon) in the same session.
     #[unstable(feature = "process_session_leader", reason = "recently added",
                issue = "27811")]
index 0eebe5af9197dc07601845769e924ef1071f60e4..c2145ac875ac3242e41f9a4bea957b853d11513a 100644 (file)
@@ -27,6 +27,7 @@ use vec::Vec;
 
 pub struct File(FileDesc);
 
+#[derive(Clone)]
 pub struct FileAttr {
     stat: raw::stat,
 }
@@ -542,7 +543,7 @@ pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
 }
 
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
-    use fs::{File, PathExt, set_permissions};
+    use fs::{File, set_permissions};
     if !from.is_file() {
         return Err(Error::new(ErrorKind::InvalidInput,
                               "the source path is not an existing regular file"))
index 964bc08ff4e10b3c835f8a9355923490fad74925..3a88f36399eb25e79d34e20cdd1a2cc9d08c6488 100644 (file)
@@ -49,7 +49,7 @@ pub mod time;
 pub mod stdio;
 
 pub fn init() {
-    // By default, some platforms will send a *signal* when a EPIPE error
+    // By default, some platforms will send a *signal* when an EPIPE error
     // would otherwise be delivered. This runtime doesn't install a SIGPIPE
     // handler, causing it to kill the program, which isn't exactly what we
     // want!
index 94c4d04ea30bbe15192a34e088f1819855910711..59b385b94810bedefe5d3e3b29c81488f116008e 100644 (file)
@@ -187,10 +187,10 @@ pub fn current_exe() -> io::Result<PathBuf> {
     unsafe {
         use libc::funcs::bsd44::*;
         use libc::consts::os::extra::*;
-        let mut mib = vec![CTL_KERN as c_int,
-                           KERN_PROC as c_int,
-                           KERN_PROC_PATHNAME as c_int,
-                           -1 as c_int];
+        let mut mib = [CTL_KERN as c_int,
+                       KERN_PROC as c_int,
+                       KERN_PROC_PATHNAME as c_int,
+                       -1 as c_int];
         let mut sz: libc::size_t = 0;
         let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
                          ptr::null_mut(), &mut sz, ptr::null_mut(),
@@ -213,7 +213,12 @@ pub fn current_exe() -> io::Result<PathBuf> {
     ::fs::read_link("/proc/curproc/file")
 }
 
-#[cfg(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"))]
+#[cfg(target_os = "netbsd")]
+pub fn current_exe() -> io::Result<PathBuf> {
+    ::fs::read_link("/proc/curproc/exe")
+}
+
+#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
 pub fn current_exe() -> io::Result<PathBuf> {
     use sync::StaticMutex;
     static LOCK: StaticMutex = StaticMutex::new();
@@ -338,7 +343,7 @@ pub fn args() -> Args {
         let args = objc_msgSend(info, arguments_sel);
 
         let cnt: usize = mem::transmute(objc_msgSend(args, count_sel));
-        for i in (0..cnt) {
+        for i in 0..cnt {
             let tmp = objc_msgSend(args, object_at_sel, i);
             let utf_c_str: *const libc::c_char =
                 mem::transmute(objc_msgSend(tmp, utf8_sel));
index 12ca31ce5e1e40383efd076cb33f705ed16637a9..7f50e75f6fc6498e6630cb63cbf0e1a4fab8ebc3 100644 (file)
@@ -450,8 +450,18 @@ mod tests {
     use slice;
     use sys::{self, c, cvt, pipe};
 
+    macro_rules! t {
+        ($e:expr) => {
+            match $e {
+                Ok(t) => t,
+                Err(e) => panic!("received error for `{}`: {}", stringify!($e), e),
+            }
+        }
+    }
+
     #[cfg(not(target_os = "android"))]
     extern {
+        #[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")]
         fn sigaddset(set: *mut c::sigset_t, signum: libc::c_int) -> libc::c_int;
     }
 
@@ -472,24 +482,26 @@ mod tests {
         unsafe {
             // Test to make sure that a signal mask does not get inherited.
             let cmd = Command::new(OsStr::new("cat"));
-            let (stdin_read, stdin_write) = sys::pipe::anon_pipe().unwrap();
-            let (stdout_read, stdout_write) = sys::pipe::anon_pipe().unwrap();
+            let (stdin_read, stdin_write) = t!(sys::pipe::anon_pipe());
+            let (stdout_read, stdout_write) = t!(sys::pipe::anon_pipe());
 
             let mut set: c::sigset_t = mem::uninitialized();
             let mut old_set: c::sigset_t = mem::uninitialized();
-            cvt(c::sigemptyset(&mut set)).unwrap();
-            cvt(sigaddset(&mut set, libc::SIGINT)).unwrap();
-            cvt(c::pthread_sigmask(c::SIG_SETMASK, &set, &mut old_set)).unwrap();
+            t!(cvt(c::sigemptyset(&mut set)));
+            t!(cvt(sigaddset(&mut set, libc::SIGINT)));
+            t!(cvt(c::pthread_sigmask(c::SIG_SETMASK, &set, &mut old_set)));
 
-            let cat = Process::spawn(&cmd, Stdio::Raw(stdin_read.raw()),
-                                           Stdio::Raw(stdout_write.raw()),
-                                           Stdio::None).unwrap();
+            let cat = t!(Process::spawn(&cmd, Stdio::Raw(stdin_read.raw()),
+                                              Stdio::Raw(stdout_write.raw()),
+                                              Stdio::None));
             drop(stdin_read);
             drop(stdout_write);
 
-            cvt(c::pthread_sigmask(c::SIG_SETMASK, &old_set, ptr::null_mut())).unwrap();
+            t!(cvt(c::pthread_sigmask(c::SIG_SETMASK, &old_set,
+                                      ptr::null_mut())));
 
-            cvt(libc::funcs::posix88::signal::kill(cat.id() as libc::pid_t, libc::SIGINT)).unwrap();
+            t!(cvt(libc::funcs::posix88::signal::kill(cat.id() as libc::pid_t,
+                                                      libc::SIGINT)));
             // We need to wait until SIGINT is definitely delivered. The
             // easiest way is to write something to cat, and try to read it
             // back: if SIGINT is unmasked, it'll get delivered when cat is
@@ -503,7 +515,7 @@ mod tests {
                 assert!(ret == 0);
             }
 
-            cat.wait().unwrap();
+            t!(cat.wait());
         }
     }
 }
index 441313bc639935dd8046b8510eaa217611e5cc92..f5fd11b61b1e67efef59b9c50f31075b3fc8836a 100644 (file)
@@ -34,7 +34,7 @@ impl Drop for Handler {
 #[cfg(any(target_os = "linux",
           target_os = "macos",
           target_os = "bitrig",
-          target_os = "netbsd",
+          all(target_os = "netbsd", not(target_vendor = "rumprun")),
           target_os = "openbsd"))]
 mod imp {
     use super::Handler;
@@ -143,7 +143,7 @@ mod imp {
 #[cfg(not(any(target_os = "linux",
               target_os = "macos",
               target_os = "bitrig",
-              target_os = "netbsd",
+              all(target_os = "netbsd", not(target_vendor = "rumprun")),
               target_os = "openbsd")))]
 mod imp {
     use ptr;
index 4e49b6473c94b0c764d84a02c94f0524ee80bdfe..954bfbb6b18b7e33d4111014f6558185453cf81f 100644 (file)
@@ -40,6 +40,7 @@ extern {
     pub fn pthread_cond_signal(cond: *mut pthread_cond_t) -> libc::c_int;
     pub fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> libc::c_int;
     pub fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> libc::c_int;
+    #[cfg_attr(target_os = "netbsd", link_name = "__gettimeofday50")]
     pub fn gettimeofday(tp: *mut libc::timeval,
                         tz: *mut libc::c_void) -> libc::c_int;
 
@@ -55,7 +56,6 @@ extern {
 #[cfg(any(target_os = "freebsd",
           target_os = "dragonfly",
           target_os = "bitrig",
-          target_os = "netbsd",
           target_os = "openbsd"))]
 mod os {
     use libc;
@@ -249,3 +249,67 @@ mod os {
     };
     pub const PTHREAD_MUTEX_RECURSIVE: libc::c_int = 1;
 }
+
+#[cfg(target_os = "netbsd")]
+mod os {
+    use libc;
+
+    // size of the type minus width of the magic and alignment field
+    #[cfg(target_arch = "x86_64")]
+    const __PTHREAD_MUTEX_SIZE__: usize = 48 - 4 - 8;
+
+    #[cfg(target_arch = "x86_64")]
+    const __PTHREAD_MUTEXATTR_SIZE__: usize = 16 - 8; // no magic field
+
+    #[cfg(target_arch = "x86_64")]
+    const __PTHREAD_COND_SIZE__: usize = 40 - 4 - 8;
+
+    #[cfg(target_arch = "x86_64")]
+    const __PTHREAD_RWLOCK_SIZE__: usize = 64 - 4 - 8;
+
+    const _PTHREAD_MUTEX_MAGIC_INIT: libc::c_uint = 0x33330003;
+    const _PTHREAD_COND_MAGIC_INIT: libc::c_uint = 0x55550005;
+    const _PTHREAD_RWLOCK_MAGIC_INIT: libc::c_uint = 0x99990009;
+
+    #[repr(C)]
+    pub struct pthread_mutex_t {
+        __magic: libc::c_uint,
+        __opaque: [u8; __PTHREAD_MUTEX_SIZE__],
+        __align: libc::c_longlong,
+    }
+    #[repr(C)]
+    pub struct pthread_mutexattr_t {
+        __opaque: [u8; __PTHREAD_MUTEXATTR_SIZE__],
+        __align: libc::c_longlong,
+    }
+    #[repr(C)]
+    pub struct pthread_cond_t {
+        __magic: libc::c_uint,
+        __opaque: [u8; __PTHREAD_COND_SIZE__],
+        __align: libc::c_longlong,
+    }
+    #[repr(C)]
+    pub struct pthread_rwlock_t {
+        __magic: libc::c_uint,
+        __opaque: [u8; __PTHREAD_RWLOCK_SIZE__],
+        __align: libc::c_longlong,
+    }
+
+    pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
+        __magic: _PTHREAD_MUTEX_MAGIC_INIT,
+        __opaque: [0; __PTHREAD_MUTEX_SIZE__],
+        __align: 0,
+    };
+    pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
+        __magic: _PTHREAD_COND_MAGIC_INIT,
+        __opaque: [0; __PTHREAD_COND_SIZE__],
+        __align: 0,
+    };
+    pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
+        __magic: _PTHREAD_RWLOCK_MAGIC_INIT,
+        __opaque: [0; __PTHREAD_RWLOCK_SIZE__],
+        __align: 0,
+    };
+
+    pub const PTHREAD_MUTEX_RECURSIVE: libc::c_int = 2;
+}
index 268ec7fe3568718f2470c0da1d3df1de8383280a..b7968e9344f3c873f70260d46083c217788bfe78 100644 (file)
@@ -102,7 +102,6 @@ impl Thread {
     #[cfg(any(target_os = "freebsd",
               target_os = "dragonfly",
               target_os = "bitrig",
-              target_os = "netbsd",
               target_os = "openbsd"))]
     pub fn set_name(name: &str) {
         extern {
@@ -126,6 +125,21 @@ impl Thread {
         }
     }
 
+    #[cfg(target_os = "netbsd")]
+    pub fn set_name(name: &str) {
+        extern {
+            fn pthread_setname_np(thread: libc::pthread_t,
+                                  name: *const libc::c_char,
+                                  arg: *mut libc::c_void) -> libc::c_int;
+        }
+        let cname = CString::new(&b"%s"[..]).unwrap();
+        let carg = CString::new(name).unwrap();
+        unsafe {
+            pthread_setname_np(pthread_self(), cname.as_ptr(),
+                               carg.as_ptr() as *mut libc::c_void);
+        }
+    }
+
     pub fn sleep(dur: Duration) {
         let mut ts = libc::timespec {
             tv_sec: dur.as_secs() as libc::time_t,
@@ -160,7 +174,7 @@ impl Drop for Thread {
 #[cfg(all(not(target_os = "linux"),
           not(target_os = "macos"),
           not(target_os = "bitrig"),
-          not(target_os = "netbsd"),
+          not(all(target_os = "netbsd", not(target_vendor = "rumprun"))),
           not(target_os = "openbsd")))]
 pub mod guard {
     pub unsafe fn current() -> Option<usize> { None }
@@ -171,7 +185,7 @@ pub mod guard {
 #[cfg(any(target_os = "linux",
           target_os = "macos",
           target_os = "bitrig",
-          target_os = "netbsd",
+          all(target_os = "netbsd", not(target_vendor = "rumprun")),
           target_os = "openbsd"))]
 #[allow(unused_imports)]
 pub mod guard {
@@ -191,13 +205,12 @@ pub mod guard {
 
     #[cfg(any(target_os = "macos",
               target_os = "bitrig",
-              target_os = "netbsd",
               target_os = "openbsd"))]
     unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
         current().map(|s| s as *mut libc::c_void)
     }
 
-    #[cfg(any(target_os = "linux", target_os = "android"))]
+    #[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd"))]
     unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
         use super::pthread_attr_init;
 
@@ -263,7 +276,7 @@ pub mod guard {
               pthread_get_stacksize_np(pthread_self())) as usize)
     }
 
-    #[cfg(any(target_os = "openbsd", target_os = "netbsd", target_os = "bitrig"))]
+    #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
     pub unsafe fn current() -> Option<usize> {
         #[repr(C)]
         struct stack_t {
@@ -290,7 +303,7 @@ pub mod guard {
         })
     }
 
-    #[cfg(any(target_os = "linux", target_os = "android"))]
+    #[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd"))]
     pub unsafe fn current() -> Option<usize> {
         use super::pthread_attr_init;
 
@@ -307,13 +320,17 @@ pub mod guard {
             let mut size = 0;
             assert_eq!(pthread_attr_getstack(&attr, &mut stackaddr, &mut size), 0);
 
-            ret = Some(stackaddr as usize + guardsize as usize);
+            ret = if cfg!(target_os = "netbsd") {
+                Some(stackaddr as usize)
+            } else {
+                Some(stackaddr as usize + guardsize as usize)
+            };
         }
         assert_eq!(pthread_attr_destroy(&mut attr), 0);
         ret
     }
 
-    #[cfg(any(target_os = "linux", target_os = "android"))]
+    #[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd"))]
     extern {
         fn pthread_getattr_np(native: libc::pthread_t,
                               attr: *mut libc::pthread_attr_t) -> libc::c_int;
@@ -339,6 +356,7 @@ pub mod guard {
 // but that caused Debian to detect an unnecessarily strict versioned
 // dependency on libc6 (#23628).
 #[cfg(target_os = "linux")]
+#[allow(deprecated)]
 fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
     use dynamic_lib::DynamicLibrary;
     use sync::Once;
index db0d0f150613953e5100878c7930ae1468656e73..73b66877588146e5cee37770ca2214955057b930 100644 (file)
@@ -86,7 +86,9 @@ mod inner {
     #[link(name = "rt")]
     extern {}
 
+
     extern {
+        #[cfg_attr(target_os = "netbsd", link_name = "__clock_gettime50")]
         fn clock_gettime(clk_id: libc::c_int, tp: *mut libc::timespec) -> libc::c_int;
     }
 
index 9534a107d1616417e3da22849ebff4979fedd7a3..b562e772b9c2c921d20413c1a02ac72ef5368495 100644 (file)
@@ -22,7 +22,7 @@
 //! copy of that function in my mingw install (maybe it was broken?). Instead,
 //! this takes the route of using StackWalk64 in order to walk the stack.
 
-#![allow(dead_code)]
+#![allow(dead_code, deprecated)]
 
 use io::prelude::*;
 
index 30c7e5a52b7c776e688e183d5ec21a88014e4d52..a9eb4db2f534e5fdcba1f4914ab007f4521f9c4a 100644 (file)
@@ -83,6 +83,8 @@ pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
 pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15;
 pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
 
+pub const ERROR_PATH_NOT_FOUND: libc::c_int = 3;
+
 #[repr(C)]
 #[cfg(target_arch = "x86")]
 pub struct WSADATA {
@@ -182,6 +184,7 @@ pub struct CONSOLE_SCREEN_BUFFER_INFO {
 pub type PCONSOLE_SCREEN_BUFFER_INFO = *mut CONSOLE_SCREEN_BUFFER_INFO;
 
 #[repr(C)]
+#[derive(Clone)]
 pub struct WIN32_FILE_ATTRIBUTE_DATA {
     pub dwFileAttributes: libc::DWORD,
     pub ftCreationTime: libc::FILETIME,
index e9d98b36a43f8e9089b059b1b4b653d37a3aeddd..fb2456564eb8d4fbb7b6d81d1428c98f0eda4029 100644 (file)
@@ -27,6 +27,7 @@ use vec::Vec;
 
 pub struct File { handle: Handle }
 
+#[derive(Clone)]
 pub struct FileAttr {
     data: c::WIN32_FILE_ATTRIBUTE_DATA,
     reparse_tag: libc::DWORD,
@@ -583,6 +584,8 @@ fn get_path(f: &File) -> io::Result<PathBuf> {
 pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
     let mut opts = OpenOptions::new();
     opts.read(true);
+    // This flag is so we can open directories too
+    opts.flags_and_attributes(c::FILE_FLAG_BACKUP_SEMANTICS);
     let f = try!(File::open(p, &opts));
     get_path(&f)
 }
index 04bb5e5ea38331d99f614affc4b7f45cd31354fa..4df3c561ab1c3d51ced9427cfd486e51d712348c 100644 (file)
@@ -51,6 +51,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
         libc::ERROR_ALREADY_EXISTS => ErrorKind::AlreadyExists,
         libc::ERROR_BROKEN_PIPE => ErrorKind::BrokenPipe,
         libc::ERROR_FILE_NOT_FOUND => ErrorKind::NotFound,
+        c::ERROR_PATH_NOT_FOUND => ErrorKind::NotFound,
         libc::ERROR_NO_DATA => ErrorKind::BrokenPipe,
         libc::ERROR_OPERATION_ABORTED => ErrorKind::TimedOut,
 
@@ -75,8 +76,8 @@ fn to_utf16_os(s: &OsStr) -> Vec<u16> {
     v
 }
 
-// Many Windows APIs follow a pattern of where we hand the a buffer and then
-// they will report back to us how large the buffer should be or how many bytes
+// Many Windows APIs follow a pattern of where we hand a buffer and then they
+// will report back to us how large the buffer should be or how many bytes
 // currently reside in the buffer. This function is an abstraction over these
 // functions by making them easier to call.
 //
index 277c3d14c0ec5515e4a2396986ede72ac9cdae93..b770156582d3bd6ff87ba053d1fd7af9833bc235 100644 (file)
@@ -22,7 +22,7 @@
 //!    more details.
 //!
 //! 3. While CriticalSection is fair and SRWLock is not, the current Rust policy
-//!    is there there are no guarantees of fairness.
+//!    is that there are no guarantees of fairness.
 //!
 //! The downside of this approach, however, is that SRWLock is not available on
 //! Windows XP, so we continue to have a fallback implementation where
index 8d3c93bb7b17605da002284176104d516c525b31..e27bef0b1e9898becff3429b8456561c1aab53e2 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(deprecated)]
+
 use dynamic_lib::DynamicLibrary;
 use io;
 use io::prelude::*;
index 81d19374fea2d06db7b07911109ae48dc4c5e2c8..6f1db5df7db2aa62d664b48ae97a4e0fec1ead38 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(deprecated)]
+
 use sys_common::backtrace::{output, output_fileline};
 use ffi::CStr;
 use dynamic_lib::DynamicLibrary;
index 43c23ec8a47157fb69d680c89d416d654838feea..9b8f63997b64278ffd88bbcf282cb8a5e6c02ad0 100644 (file)
 
 use prelude::v1::*;
 
-use alloc::boxed::FnBox;
 use any::Any;
 use cell::UnsafeCell;
 use fmt;
@@ -249,16 +248,6 @@ impl Builder {
     pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
         F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
     {
-        unsafe {
-            self.spawn_inner(Box::new(f)).map(JoinHandle)
-        }
-    }
-
-    // NB: this function is unsafe as the lifetime parameter of the code to run
-    //     in the new thread is not tied into the return value, and the return
-    //     value must not outlast that lifetime.
-    unsafe fn spawn_inner<'a, T: Send>(self, f: Box<FnBox() -> T + Send + 'a>)
-                                       -> io::Result<JoinInner<T>> {
         let Builder { name, stack_size } = self;
 
         let stack_size = stack_size.unwrap_or(util::min_stack());
@@ -266,29 +255,34 @@ impl Builder {
         let my_thread = Thread::new(name);
         let their_thread = my_thread.clone();
 
-        let my_packet = Arc::new(UnsafeCell::new(None));
+        let my_packet : Arc<UnsafeCell<Option<Result<T>>>>
+            = Arc::new(UnsafeCell::new(None));
         let their_packet = my_packet.clone();
 
         let main = move || {
             if let Some(name) = their_thread.name() {
                 imp::Thread::set_name(name);
             }
-            thread_info::set(imp::guard::current(), their_thread);
-            let mut output = None;
-            let try_result = {
-                let ptr = &mut output;
-                unwind::try(move || *ptr = Some(f()))
-            };
-            *their_packet.get() = Some(try_result.map(|()| {
-                output.unwrap()
-            }));
+            unsafe {
+                thread_info::set(imp::guard::current(), their_thread);
+                let mut output = None;
+                let try_result = {
+                    let ptr = &mut output;
+                    unwind::try(move || *ptr = Some(f()))
+                };
+                *their_packet.get() = Some(try_result.map(|()| {
+                    output.unwrap()
+                }));
+            }
         };
 
-        Ok(JoinInner {
-            native: Some(try!(imp::Thread::new(stack_size, Box::new(main)))),
+        Ok(JoinHandle(JoinInner {
+            native: unsafe {
+                Some(try!(imp::Thread::new(stack_size, Box::new(main))))
+            },
             thread: my_thread,
             packet: Packet(my_packet),
-        })
+        }))
     }
 }
 
index 2135b85103294480e61df0a95f82209189195976..d18d7cbecf4c2d8d8eeff4bd1170d79ea0b080c9 100644 (file)
@@ -47,7 +47,7 @@ pub struct Duration {
 }
 
 impl Duration {
-    /// Crates a new `Duration` from the specified number of seconds and
+    /// Creates a new `Duration` from the specified number of seconds and
     /// additional nanosecond precision.
     ///
     /// If the nanoseconds is greater than 1 billion (the number of nanoseconds
index bf8c67c7ae1815632e3556d0129191b15fa3dca7..7b3c33d53a390971af4c8d6ae6b622436574f882 100644 (file)
@@ -10,8 +10,6 @@
 
 // The Rust abstract syntax tree.
 
-pub use self::AsmDialect::*;
-pub use self::AttrStyle::*;
 pub use self::BindingMode::*;
 pub use self::BinOp_::*;
 pub use self::BlockCheckMode::*;
@@ -28,7 +26,6 @@ pub use self::Item_::*;
 pub use self::KleeneOp::*;
 pub use self::Lit_::*;
 pub use self::LitIntType::*;
-pub use self::Mac_::*;
 pub use self::MacStmtStyle::*;
 pub use self::MetaItem_::*;
 pub use self::Mutability::*;
@@ -47,7 +44,6 @@ pub use self::TyParamBound::*;
 pub use self::UintTy::*;
 pub use self::UnOp::*;
 pub use self::UnsafeSource::*;
-pub use self::VariantKind::*;
 pub use self::ViewPath_::*;
 pub use self::Visibility::*;
 pub use self::PathParameters::*;
@@ -67,42 +63,42 @@ use ptr::P;
 
 use std::fmt;
 use std::rc::Rc;
+use std::borrow::Cow;
+use std::hash::{Hash, Hasher};
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 
-// FIXME #6993: in librustc, uses of "ident" should be replaced
-// by just "Name".
+/// A name is a part of an identifier, representing a string or gensym. It's
+/// the result of interning.
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct Name(pub u32);
+
+/// A SyntaxContext represents a chain of macro-expandings
+/// and renamings. Each macro expansion corresponds to
+/// a fresh u32. This u32 is a reference to a table stored
+// in thread-local storage.
+// The special value EMPTY_CTXT is used to indicate an empty
+// syntax context.
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+pub struct SyntaxContext(pub u32);
 
 /// An identifier contains a Name (index into the interner
 /// table) and a SyntaxContext to track renaming and
-/// macro expansion per Flatt et al., "Macros
-/// That Work Together"
-#[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)]
+/// macro expansion per Flatt et al., "Macros That Work Together"
+#[derive(Clone, Copy, Eq)]
 pub struct Ident {
     pub name: Name,
     pub ctxt: SyntaxContext
 }
 
-impl Ident {
-    /// Construct an identifier with the given name and an empty context:
-    pub fn new(name: Name) -> Ident { Ident {name: name, ctxt: EMPTY_CTXT}}
-}
-
-impl fmt::Debug for Ident {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "{}#{}", self.name, self.ctxt)
-    }
-}
-
-impl fmt::Display for Ident {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&self.name, f)
+impl Name {
+    pub fn as_str(self) -> token::InternedString {
+        token::InternedString::new_from_name(self)
     }
 }
 
 impl fmt::Debug for Name {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let Name(nm) = *self;
-        write!(f, "{}({})", self, nm)
+        write!(f, "{}({})", self, self.0)
     }
 }
 
@@ -112,89 +108,89 @@ impl fmt::Display for Name {
     }
 }
 
-impl PartialEq for Ident {
-    fn eq(&self, other: &Ident) -> bool {
-        if self.ctxt == other.ctxt {
-            self.name == other.name
-        } else {
-            // IF YOU SEE ONE OF THESE FAILS: it means that you're comparing
-            // idents that have different contexts. You can't fix this without
-            // knowing whether the comparison should be hygienic or non-hygienic.
-            // if it should be non-hygienic (most things are), just compare the
-            // 'name' fields of the idents. Or, even better, replace the idents
-            // with Name's.
-            //
-            // On the other hand, if the comparison does need to be hygienic,
-            // one example and its non-hygienic counterpart would be:
-            //      syntax::parse::token::Token::mtwt_eq
-            //      syntax::ext::tt::macro_parser::token_name_eq
-            panic!("not allowed to compare these idents: {:?}, {:?}. \
-                   Probably related to issue \\#6993", self, other);
-        }
+impl Encodable for Name {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        s.emit_str(&self.as_str())
     }
 }
 
-/// A SyntaxContext represents a chain of macro-expandings
-/// and renamings. Each macro expansion corresponds to
-/// a fresh u32
+impl Decodable for Name {
+    fn decode<D: Decoder>(d: &mut D) -> Result<Name, D::Error> {
+        Ok(token::intern(&try!(d.read_str())[..]))
+    }
+}
 
-// I'm representing this syntax context as an index into
-// a table, in order to work around a compiler bug
-// that's causing unreleased memory to cause core dumps
-// and also perhaps to save some work in destructor checks.
-// the special uint '0' will be used to indicate an empty
-// syntax context.
+pub const EMPTY_CTXT : SyntaxContext = SyntaxContext(0);
 
-// this uint is a reference to a table stored in thread-local
-// storage.
-pub type SyntaxContext = u32;
-pub const EMPTY_CTXT : SyntaxContext = 0;
-pub const ILLEGAL_CTXT : SyntaxContext = 1;
+impl Ident {
+    pub fn new(name: Name, ctxt: SyntaxContext) -> Ident {
+        Ident {name: name, ctxt: ctxt}
+    }
+    pub fn with_empty_ctxt(name: Name) -> Ident {
+        Ident {name: name, ctxt: EMPTY_CTXT}
+    }
+}
 
-/// A name is a part of an identifier, representing a string or gensym. It's
-/// the result of interning.
-#[derive(Eq, Ord, PartialEq, PartialOrd, Hash,
-           RustcEncodable, RustcDecodable, Clone, Copy)]
-pub struct Name(pub u32);
+impl PartialEq for Ident {
+    fn eq(&self, other: &Ident) -> bool {
+        if self.ctxt != other.ctxt {
+            // There's no one true way to compare Idents. They can be compared
+            // non-hygienically `id1.name == id2.name`, hygienically
+            // `mtwt::resolve(id1) == mtwt::resolve(id2)`, or even member-wise
+            // `(id1.name, id1.ctxt) == (id2.name, id2.ctxt)` depending on the situation.
+            // Ideally, PartialEq should not be implemented for Ident at all, but that
+            // would be too impractical, because many larger structures (Token, in particular)
+            // including Idents as their parts derive PartialEq and use it for non-hygienic
+            // comparisons. That's why PartialEq is implemented and defaults to non-hygienic
+            // comparison. Hash is implemented too and is consistent with PartialEq, i.e. only
+            // the name of Ident is hashed. Still try to avoid comparing idents in your code
+            // (especially as keys in hash maps), use one of the three methods listed above
+            // explicitly.
+            //
+            // If you see this panic, then some idents from different contexts were compared
+            // non-hygienically. It's likely a bug. Use one of the three comparison methods
+            // listed above explicitly.
 
-impl<T: AsRef<str>> PartialEq<T> for Name {
-    fn eq(&self, other: &T) -> bool {
-        self.as_str() == other.as_ref()
+            panic!("idents with different contexts are compared with operator `==`: \
+                {:?}, {:?}.", self, other);
+        }
+
+        self.name == other.name
     }
 }
 
-impl Name {
-    pub fn as_str(&self) -> token::InternedString {
-        token::InternedString::new_from_name(*self)
+impl Hash for Ident {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.name.hash(state)
     }
+}
 
-    pub fn usize(&self) -> usize {
-        let Name(nm) = *self;
-        nm as usize
+impl fmt::Debug for Ident {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}#{}", self.name, self.ctxt.0)
     }
+}
 
-    pub fn ident(&self) -> Ident {
-        Ident { name: *self, ctxt: 0 }
+impl fmt::Display for Ident {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&self.name, f)
     }
 }
 
-/// A mark represents a unique id associated with a macro expansion
-pub type Mrk = u32;
-
 impl Encodable for Ident {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_str(&self.name.as_str())
+        self.name.encode(s)
     }
 }
 
 impl Decodable for Ident {
     fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
-        Ok(str_to_ident(&try!(d.read_str())[..]))
+        Ok(Ident::with_empty_ctxt(try!(Name::decode(d))))
     }
 }
 
-/// Function name (not all functions have names)
-pub type FnIdent = Option<Ident>;
+/// A mark represents a unique id associated with a macro expansion
+pub type Mrk = u32;
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)]
 pub struct Lifetime {
@@ -378,6 +374,11 @@ pub const CRATE_NODE_ID: NodeId = 0;
 /// small, positive ids.
 pub const DUMMY_NODE_ID: NodeId = !0;
 
+pub trait NodeIdAssigner {
+    fn next_node_id(&self) -> NodeId;
+    fn peek_node_id(&self) -> NodeId;
+}
+
 /// The AST represents all type param bounds as types.
 /// typeck::collect::compute_bounds matches these against
 /// the "special" built-in traits (see middle::lang_items) and
@@ -671,8 +672,6 @@ pub type BinOp = Spanned<BinOp_>;
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum UnOp {
-    /// The `box` operator
-    UnUniq,
     /// The `*` operator for dereferencing
     UnDeref,
     /// The `!` operator for logical inversion
@@ -687,7 +686,8 @@ pub type Stmt = Spanned<Stmt_>;
 impl fmt::Debug for Stmt {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "stmt({}: {})",
-               ast_util::stmt_id(self),
+               ast_util::stmt_id(self)
+                   .map_or(Cow::Borrowed("<macro>"),|id|Cow::Owned(id.to_string())),
                pprust::stmt_to_string(self))
     }
 }
@@ -764,8 +764,6 @@ pub type SpannedIdent = Spanned<Ident>;
 pub enum BlockCheckMode {
     DefaultBlock,
     UnsafeBlock(UnsafeSource),
-    PushUnsafeBlock(UnsafeSource),
-    PopUnsafeBlock(UnsafeSource),
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
@@ -790,8 +788,10 @@ impl fmt::Debug for Expr {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Expr_ {
+    /// A `box x` expression.
+    ExprBox(P<Expr>),
     /// First expr is the place; second expr is the value.
-    ExprBox(Option<P<Expr>>, P<Expr>),
+    ExprInPlace(P<Expr>, P<Expr>),
     /// An array (`[a, b, c, d]`)
     ExprVec(Vec<P<Expr>>),
     /// A function call
@@ -832,19 +832,16 @@ pub enum Expr_ {
     ///
     /// This is desugared to a `match` expression.
     ExprIfLet(P<Pat>, P<Expr>, P<Block>, Option<P<Expr>>),
-    // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
     /// A while loop, with an optional label
     ///
     /// `'label: while expr { block }`
     ExprWhile(P<Expr>, P<Block>, Option<Ident>),
-    // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
     /// A while-let loop, with an optional label
     ///
     /// `'label: while let pat = expr { block }`
     ///
     /// This is desugared to a combination of `loop` and `match` expressions.
     ExprWhileLet(P<Pat>, P<Expr>, P<Block>, Option<Ident>),
-    // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
     /// A for loop, with an optional label
     ///
     /// `'label: for pat in expr { block }`
@@ -854,11 +851,9 @@ pub enum Expr_ {
     /// Conditionless loop (can be exited with break, continue, or return)
     ///
     /// `'label: loop { block }`
-    // FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
     ExprLoop(P<Block>, Option<Ident>),
-    /// A `match` block, with a source that indicates whether or not it is
-    /// the result of a desugaring, and if so, which kind.
-    ExprMatch(P<Expr>, Vec<Arm>, MatchSource),
+    /// A `match` block.
+    ExprMatch(P<Expr>, Vec<Arm>),
     /// A closure (for example, `move |a, b, c| {a + b + c}`)
     ExprClosure(CaptureClause, P<FnDecl>, P<Block>),
     /// A block (`{ ... }`)
@@ -937,14 +932,6 @@ pub struct QSelf {
     pub position: usize
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
-pub enum MatchSource {
-    Normal,
-    IfLetDesugar { contains_else_clause: bool },
-    WhileLetDesugar,
-    ForLoopDesugar,
-}
-
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum CaptureClause {
     CaptureByValue,
@@ -1038,8 +1025,8 @@ impl TokenTree {
         match *self {
             TtToken(_, token::DocComment(name)) => {
                 match doc_comment_style(&name.as_str()) {
-                    AttrOuter => 2,
-                    AttrInner => 3
+                    AttrStyle::Outer => 2,
+                    AttrStyle::Inner => 3
                 }
             }
             TtToken(_, token::SpecialVarNt(..)) => 2,
@@ -1060,7 +1047,7 @@ impl TokenTree {
                 TtToken(sp, token::Pound)
             }
             (&TtToken(sp, token::DocComment(name)), 1)
-            if doc_comment_style(&name.as_str()) == AttrInner => {
+            if doc_comment_style(&name.as_str()) == AttrStyle::Inner => {
                 TtToken(sp, token::Not)
             }
             (&TtToken(sp, token::DocComment(name)), _) => {
@@ -1132,12 +1119,13 @@ pub type Mac = Spanned<Mac_>;
 /// is being invoked, and the vector of token-trees contains the source
 /// of the macro invocation.
 ///
-/// There's only one flavor, now, so this could presumably be simplified.
+/// NB: the additional ident for a macro_rules-style macro is actually
+/// stored in the enclosing item. Oog.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum Mac_ {
-    // NB: the additional ident for a macro_rules-style macro is actually
-    // stored in the enclosing item. Oog.
-    MacInvocTT(Path, Vec<TokenTree>, SyntaxContext),   // new macro-invocation
+pub struct Mac_ {
+    pub path: Path,
+    pub tts: Vec<TokenTree>,
+    pub ctxt: SyntaxContext,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
@@ -1213,13 +1201,6 @@ pub struct MutTy {
     pub mutbl: Mutability,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct TypeField {
-    pub ident: Ident,
-    pub mt: MutTy,
-    pub span: Span,
-}
-
 /// Represents a method's signature in a trait declaration,
 /// or in an implementation.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@ -1440,8 +1421,8 @@ pub enum Ty_ {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum AsmDialect {
-    AsmAtt,
-    AsmIntel
+    Att,
+    Intel,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@ -1587,20 +1568,6 @@ pub struct ForeignMod {
     pub items: Vec<P<ForeignItem>>,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct VariantArg {
-    pub ty: P<Ty>,
-    pub id: NodeId,
-}
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum VariantKind {
-    /// Tuple variant, e.g. `Foo(A, B)`
-    TupleVariantKind(Vec<VariantArg>),
-    /// Struct variant, e.g. `Foo {x: A, y: B}`
-    StructVariantKind(P<StructDef>),
-}
-
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct EnumDef {
     pub variants: Vec<P<Variant>>,
@@ -1610,11 +1577,9 @@ pub struct EnumDef {
 pub struct Variant_ {
     pub name: Ident,
     pub attrs: Vec<Attribute>,
-    pub kind: VariantKind,
-    pub id: NodeId,
+    pub data: VariantData,
     /// Explicit discriminant, eg `Foo = 1`
     pub disr_expr: Option<P<Expr>>,
-    pub vis: Visibility,
 }
 
 pub type Variant = Spanned<Variant_>;
@@ -1641,6 +1606,13 @@ impl PathListItem_ {
         }
     }
 
+    pub fn name(&self) -> Option<Ident> {
+        match *self {
+            PathListIdent { name, .. } => Some(name),
+            PathListMod { .. } => None,
+        }
+    }
+
     pub fn rename(&self) -> Option<Ident> {
         match *self {
             PathListIdent { rename, .. } | PathListMod { rename, .. } => rename
@@ -1677,8 +1649,8 @@ pub type Attribute = Spanned<Attribute_>;
 /// distinguished for pretty-printing.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
 pub enum AttrStyle {
-    AttrOuter,
-    AttrInner,
+    Outer,
+    Inner,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
@@ -1766,13 +1738,45 @@ impl StructFieldKind {
     }
 }
 
+/// Fields and Ids of enum variants and structs
+///
+/// For enum variants: `NodeId` represents both an Id of the variant itself (relevant for all
+/// variant kinds) and an Id of the variant's constructor (not relevant for `Struct`-variants).
+/// One shared Id can be successfully used for these two purposes.
+/// Id of the whole enum lives in `Item`.
+///
+/// For structs: `NodeId` represents an Id of the structure's constructor, so it is not actually
+/// used for `Struct`-structs (but still presents). Structures don't have an analogue of "Id of
+/// the variant itself" from enum variants.
+/// Id of the whole struct lives in `Item`.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct StructDef {
-    /// Fields, not including ctor
-    pub fields: Vec<StructField>,
-    /// ID of the constructor. This is only used for tuple- or enum-like
-    /// structs.
-    pub ctor_id: Option<NodeId>,
+pub enum VariantData {
+    Struct(Vec<StructField>, NodeId),
+    Tuple(Vec<StructField>, NodeId),
+    Unit(NodeId),
+}
+
+impl VariantData {
+    pub fn fields(&self) -> &[StructField] {
+        match *self {
+            VariantData::Struct(ref fields, _) | VariantData::Tuple(ref fields, _) => fields,
+            _ => &[],
+        }
+    }
+    pub fn id(&self) -> NodeId {
+        match *self {
+            VariantData::Struct(_, id) | VariantData::Tuple(_, id) | VariantData::Unit(id) => id
+        }
+    }
+    pub fn is_struct(&self) -> bool {
+        if let VariantData::Struct(..) = *self { true } else { false }
+    }
+    pub fn is_tuple(&self) -> bool {
+        if let VariantData::Tuple(..) = *self { true } else { false }
+    }
+    pub fn is_unit(&self) -> bool {
+        if let VariantData::Unit(..) = *self { true } else { false }
+    }
 }
 
 /*
@@ -1816,7 +1820,7 @@ pub enum Item_ {
     /// An enum definition, e.g. `enum Foo<A, B> {C<A>, D<B>}`
     ItemEnum(EnumDef, Generics),
     /// A struct definition, e.g. `struct Foo<A> {x: A}`
-    ItemStruct(P<StructDef>, Generics),
+    ItemStruct(VariantData, Generics),
     /// Represents a Trait Declaration
     ItemTrait(Unsafety,
               Generics,
index d024ff117f579d97cbffd8bd11a337b39b92b0b8..8c3360512d512f632880670a7929f42bfabae4b4 100644 (file)
@@ -28,12 +28,12 @@ pub fn path_name_i(idents: &[Ident]) -> String {
     idents.iter().map(|i| i.to_string()).collect::<Vec<String>>().join("::")
 }
 
-pub fn stmt_id(s: &Stmt) -> NodeId {
+pub fn stmt_id(s: &Stmt) -> Option<NodeId> {
     match s.node {
-      StmtDecl(_, id) => id,
-      StmtExpr(_, id) => id,
-      StmtSemi(_, id) => id,
-      StmtMac(..) => panic!("attempted to analyze unexpanded stmt")
+      StmtDecl(_, id) => Some(id),
+      StmtExpr(_, id) => Some(id),
+      StmtSemi(_, id) => Some(id),
+      StmtMac(..) => None,
     }
 }
 
@@ -101,10 +101,9 @@ pub fn is_by_value_unop(u: UnOp) -> bool {
 
 pub fn unop_to_string(op: UnOp) -> &'static str {
     match op {
-      UnUniq => "box() ",
-      UnDeref => "*",
-      UnNot => "!",
-      UnNeg => "-",
+        UnDeref => "*",
+        UnNot => "!",
+        UnNeg => "-",
     }
 }
 
@@ -361,11 +360,6 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
                     }
                 }
             }
-            ItemEnum(ref enum_definition, _) => {
-                for variant in &enum_definition.variants {
-                    self.operation.visit_id(variant.node.id)
-                }
-            }
             _ => {}
         }
 
@@ -385,7 +379,8 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
     }
 
     fn visit_stmt(&mut self, statement: &Stmt) {
-        self.operation.visit_id(ast_util::stmt_id(statement));
+        self.operation
+            .visit_id(ast_util::stmt_id(statement).expect("attempted to visit unexpanded stmt"));
         visit::walk_stmt(self, statement)
     }
 
@@ -457,13 +452,13 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
         visit::walk_struct_field(self, struct_field)
     }
 
-    fn visit_struct_def(&mut self,
-                        struct_def: &StructDef,
+    fn visit_variant_data(&mut self,
+                        struct_def: &VariantData,
                         _: ast::Ident,
                         _: &ast::Generics,
-                        id: NodeId) {
-        self.operation.visit_id(id);
-        struct_def.ctor_id.map(|ctor_id| self.operation.visit_id(ctor_id));
+                        _: NodeId,
+                        _: Span) {
+        self.operation.visit_id(struct_def.id());
         visit::walk_struct_def(self, struct_def);
     }
 
@@ -477,12 +472,12 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
         visit::walk_impl_item(self, ii);
     }
 
-    fn visit_lifetime_ref(&mut self, lifetime: &Lifetime) {
+    fn visit_lifetime(&mut self, lifetime: &Lifetime) {
         self.operation.visit_id(lifetime.id);
     }
 
     fn visit_lifetime_def(&mut self, def: &LifetimeDef) {
-        self.visit_lifetime_ref(&def.lifetime);
+        self.visit_lifetime(&def.lifetime);
     }
 
     fn visit_trait_ref(&mut self, trait_ref: &TraitRef) {
@@ -529,12 +524,6 @@ pub fn compute_id_range_for_fn_body(fk: FnKind,
     id_visitor.operation.result
 }
 
-/// Returns true if the given struct def is tuple-like; i.e. that its fields
-/// are unnamed.
-pub fn struct_def_is_tuple_like(struct_def: &ast::StructDef) -> bool {
-    struct_def.ctor_id.is_some()
-}
-
 /// Returns true if the given pattern consists solely of an identifier
 /// and false otherwise.
 pub fn pat_is_ident(pat: P<ast::Pat>) -> bool {
@@ -577,21 +566,21 @@ mod tests {
     use ast::*;
     use super::*;
 
-    fn ident_to_segment(id : &Ident) -> PathSegment {
-        PathSegment {identifier: id.clone(),
+    fn ident_to_segment(idIdent) -> PathSegment {
+        PathSegment {identifier: id,
                      parameters: PathParameters::none()}
     }
 
     #[test] fn idents_name_eq_test() {
         assert!(segments_name_eq(
-            &[Ident{name:Name(3),ctxt:4}, Ident{name:Name(78),ctxt:82}]
-                .iter().map(ident_to_segment).collect::<Vec<PathSegment>>(),
-            &[Ident{name:Name(3),ctxt:104}, Ident{name:Name(78),ctxt:182}]
-                .iter().map(ident_to_segment).collect::<Vec<PathSegment>>()));
+            &[Ident::new(Name(3),SyntaxContext(4)), Ident::new(Name(78),SyntaxContext(82))]
+                .iter().cloned().map(ident_to_segment).collect::<Vec<PathSegment>>(),
+            &[Ident::new(Name(3),SyntaxContext(104)), Ident::new(Name(78),SyntaxContext(182))]
+                .iter().cloned().map(ident_to_segment).collect::<Vec<PathSegment>>()));
         assert!(!segments_name_eq(
-            &[Ident{name:Name(3),ctxt:4}, Ident{name:Name(78),ctxt:82}]
-                .iter().map(ident_to_segment).collect::<Vec<PathSegment>>(),
-            &[Ident{name:Name(3),ctxt:104}, Ident{name:Name(77),ctxt:182}]
-                .iter().map(ident_to_segment).collect::<Vec<PathSegment>>()));
+            &[Ident::new(Name(3),SyntaxContext(4)), Ident::new(Name(78),SyntaxContext(82))]
+                .iter().cloned().map(ident_to_segment).collect::<Vec<PathSegment>>(),
+            &[Ident::new(Name(3),SyntaxContext(104)), Ident::new(Name(77),SyntaxContext(182))]
+                .iter().cloned().map(ident_to_segment).collect::<Vec<PathSegment>>()));
     }
 }
index 7540c2ff831e932976a2e0feca58e781fd25a542..eeb832d48b0d89675574a2eab825bfd9debeafa4 100644 (file)
@@ -27,7 +27,6 @@ use ptr::P;
 
 use std::cell::{RefCell, Cell};
 use std::collections::HashSet;
-use std::fmt;
 
 thread_local! {
     static USED_ATTRS: RefCell<Vec<u64>> = RefCell::new(Vec::new())
@@ -156,7 +155,7 @@ impl AttributeMethods for Attribute {
                 InternedString::new("doc"),
                 token::intern_and_get_ident(&strip_doc_comment_decoration(
                         &comment)));
-            if self.node.style == ast::AttrOuter {
+            if self.node.style == ast::AttrStyle::Outer {
                 f(&mk_attr_outer(self.node.id, meta))
             } else {
                 f(&mk_attr_inner(self.node.id, meta))
@@ -203,7 +202,7 @@ pub fn mk_attr_id() -> AttrId {
 pub fn mk_attr_inner(id: AttrId, item: P<MetaItem>) -> Attribute {
     dummy_spanned(Attribute_ {
         id: id,
-        style: ast::AttrInner,
+        style: ast::AttrStyle::Inner,
         value: item,
         is_sugared_doc: false,
     })
@@ -213,7 +212,7 @@ pub fn mk_attr_inner(id: AttrId, item: P<MetaItem>) -> Attribute {
 pub fn mk_attr_outer(id: AttrId, item: P<MetaItem>) -> Attribute {
     dummy_spanned(Attribute_ {
         id: id,
-        style: ast::AttrOuter,
+        style: ast::AttrStyle::Outer,
         value: item,
         is_sugared_doc: false,
     })
@@ -323,7 +322,6 @@ pub enum InlineAttr {
 
 /// Determine what `#[inline]` attribute is present in `attrs`, if any.
 pub fn find_inline_attr(diagnostic: Option<&SpanHandler>, attrs: &[Attribute]) -> InlineAttr {
-    // FIXME (#2809)---validate the usage of #[inline] and #[inline]
     attrs.iter().fold(InlineAttr::None, |ia,attr| {
         match attr.node.value.node {
             MetaWord(ref n) if *n == "inline" => {
@@ -383,174 +381,223 @@ pub fn cfg_matches(diagnostic: &SpanHandler, cfgs: &[P<MetaItem>], cfg: &ast::Me
     }
 }
 
-/// Represents the #[deprecated] and friends attributes.
+/// Represents the #[stable], #[unstable] and #[deprecated] attributes.
 #[derive(RustcEncodable, RustcDecodable, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct Stability {
     pub level: StabilityLevel,
     pub feature: InternedString,
-    pub since: Option<InternedString>,
-    pub deprecated_since: Option<InternedString>,
-    // The reason for the current stability level. If deprecated, the
-    // reason for deprecation.
-    pub reason: Option<InternedString>,
-    // The relevant rust-lang issue
-    pub issue: Option<u32>
+    pub depr: Option<Deprecation>,
 }
 
 /// The available stability levels.
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Copy, Eq, Hash)]
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
 pub enum StabilityLevel {
-    Unstable,
-    Stable,
+    // Reason for the current stability level and the relevant rust-lang issue
+    Unstable { reason: Option<InternedString>, issue: u32 },
+    Stable { since: InternedString },
 }
 
-impl fmt::Display for StabilityLevel {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(self, f)
-    }
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
+pub struct Deprecation {
+    pub since: InternedString,
+    pub reason: InternedString,
 }
 
-fn find_stability_generic<'a,
-                              AM: AttrMetaMethods,
-                              I: Iterator<Item=&'a AM>>
-                             (diagnostic: &SpanHandler, attrs: I, item_sp: Span)
-                             -> (Option<Stability>, Vec<&'a AM>) {
+impl StabilityLevel {
+    pub fn is_unstable(&self) -> bool { if let Unstable {..} = *self { true } else { false }}
+    pub fn is_stable(&self) -> bool { if let Stable {..} = *self { true } else { false }}
+}
 
+fn find_stability_generic<'a, I>(diagnostic: &SpanHandler,
+                                 attrs_iter: I,
+                                 item_sp: Span)
+                                 -> Option<Stability>
+    where I: Iterator<Item = &'a Attribute>
+{
     let mut stab: Option<Stability> = None;
-    let mut deprecated: Option<(Option<InternedString>, Option<InternedString>)> = None;
-    let mut used_attrs: Vec<&'a AM> = vec![];
+    let mut depr: Option<Deprecation> = None;
 
-    'outer: for attr in attrs {
+    'outer: for attr in attrs_iter {
         let tag = attr.name();
-        let tag = &tag[..];
+        let tag = &*tag;
         if tag != "deprecated" && tag != "unstable" && tag != "stable" {
             continue // not a stability level
         }
 
-        used_attrs.push(attr);
-
-        let (feature, since, reason, issue) = match attr.meta_item_list() {
-            Some(metas) => {
-                let mut feature = None;
-                let mut since = None;
-                let mut reason = None;
-                let mut issue = None;
-                for meta in metas {
-                    match &*meta.name() {
-                        "feature" => {
-                            match meta.value_str() {
-                                Some(v) => feature = Some(v),
-                                None => {
-                                    diagnostic.span_err(meta.span, "incorrect meta item");
-                                    continue 'outer;
-                                }
+        mark_used(attr);
+
+        if let Some(metas) = attr.meta_item_list() {
+            let get = |meta: &MetaItem, item: &mut Option<InternedString>| {
+                if item.is_some() {
+                    diagnostic.span_err(meta.span, &format!("multiple '{}' items",
+                                                             meta.name()));
+                    return false
+                }
+                if let Some(v) = meta.value_str() {
+                    *item = Some(v);
+                    true
+                } else {
+                    diagnostic.span_err(meta.span, "incorrect meta item");
+                    false
+                }
+            };
+
+            match tag {
+                "deprecated" => {
+                    if depr.is_some() {
+                        diagnostic.span_err(item_sp, "multiple deprecated attributes");
+                        break
+                    }
+
+                    let mut since = None;
+                    let mut reason = None;
+                    for meta in metas {
+                        match &*meta.name() {
+                            "since" => if !get(meta, &mut since) { continue 'outer },
+                            "reason" => if !get(meta, &mut reason) { continue 'outer },
+                            _ => {
+                                diagnostic.span_err(meta.span, &format!("unknown meta item '{}'",
+                                                                        meta.name()));
+                                continue 'outer
                             }
                         }
-                        "since" => {
-                            match meta.value_str() {
-                                Some(v) => since = Some(v),
-                                None => {
-                                    diagnostic.span_err(meta.span, "incorrect meta item");
-                                    continue 'outer;
-                                }
-                            }
+                    }
+
+                    match (since, reason) {
+                        (Some(since), Some(reason)) => {
+                            depr = Some(Deprecation {
+                                since: since,
+                                reason: reason,
+                            })
                         }
-                        "reason" => {
-                            match meta.value_str() {
-                                Some(v) => reason = Some(v),
-                                None => {
-                                    diagnostic.span_err(meta.span, "incorrect meta item");
-                                    continue 'outer;
-                                }
-                            }
+                        (None, _) => {
+                            diagnostic.span_err(attr.span(), "missing 'since'");
+                            continue
                         }
-                        "issue" => {
-                            match meta.value_str().and_then(|s| s.parse().ok()) {
-                                Some(v) => issue = Some(v),
-                                None => {
-                                    diagnostic.span_err(meta.span, "incorrect meta item");
-                                    continue 'outer;
-                                }
-                            }
+                        _ => {
+                            diagnostic.span_err(attr.span(), "missing 'reason'");
+                            continue
                         }
-                        _ => {}
                     }
                 }
-                (feature, since, reason, issue)
-            }
-            None => {
-                diagnostic.span_err(attr.span(), "incorrect stability attribute type");
-                continue
-            }
-        };
+                "unstable" => {
+                    if stab.is_some() {
+                        diagnostic.span_err(item_sp, "multiple stability levels");
+                        break
+                    }
 
-        // Deprecated tags don't require feature names
-        if feature == None && tag != "deprecated" {
-            diagnostic.span_err(attr.span(), "missing 'feature'");
-        }
+                    let mut feature = None;
+                    let mut reason = None;
+                    let mut issue = None;
+                    for meta in metas {
+                        match &*meta.name() {
+                            "feature" => if !get(meta, &mut feature) { continue 'outer },
+                            "reason" => if !get(meta, &mut reason) { continue 'outer },
+                            "issue" => if !get(meta, &mut issue) { continue 'outer },
+                            _ => {
+                                diagnostic.span_err(meta.span, &format!("unknown meta item '{}'",
+                                                                        meta.name()));
+                                continue 'outer
+                            }
+                        }
+                    }
 
-        // Unstable tags don't require a version
-        if since == None && tag != "unstable" {
-            diagnostic.span_err(attr.span(), "missing 'since'");
-        }
+                    match (feature, reason, issue) {
+                        (Some(feature), reason, Some(issue)) => {
+                            stab = Some(Stability {
+                                level: Unstable {
+                                    reason: reason,
+                                    issue: {
+                                        if let Ok(issue) = issue.parse() {
+                                            issue
+                                        } else {
+                                            diagnostic.span_err(attr.span(), "incorrect 'issue'");
+                                            continue
+                                        }
+                                    }
+                                },
+                                feature: feature,
+                                depr: None,
+                            })
+                        }
+                        (None, _, _) => {
+                            diagnostic.span_err(attr.span(), "missing 'feature'");
+                            continue
+                        }
+                        _ => {
+                            diagnostic.span_err(attr.span(), "missing 'issue'");
+                            continue
+                        }
+                    }
+                }
+                "stable" => {
+                    if stab.is_some() {
+                        diagnostic.span_err(item_sp, "multiple stability levels");
+                        break
+                    }
 
-        if tag == "unstable" || tag == "stable" {
-            if stab.is_some() {
-                diagnostic.span_err(item_sp, "multiple stability levels");
-            }
+                    let mut feature = None;
+                    let mut since = None;
+                    for meta in metas {
+                        match &*meta.name() {
+                            "feature" => if !get(meta, &mut feature) { continue 'outer },
+                            "since" => if !get(meta, &mut since) { continue 'outer },
+                            _ => {
+                                diagnostic.span_err(meta.span, &format!("unknown meta item '{}'",
+                                                                        meta.name()));
+                                continue 'outer
+                            }
+                        }
+                    }
 
-            let level = match tag {
-                "unstable" => Unstable,
-                "stable" => Stable,
+                    match (feature, since) {
+                        (Some(feature), Some(since)) => {
+                            stab = Some(Stability {
+                                level: Stable {
+                                    since: since,
+                                },
+                                feature: feature,
+                                depr: None,
+                            })
+                        }
+                        (None, _) => {
+                            diagnostic.span_err(attr.span(), "missing 'feature'");
+                            continue
+                        }
+                        _ => {
+                            diagnostic.span_err(attr.span(), "missing 'since'");
+                            continue
+                        }
+                    }
+                }
                 _ => unreachable!()
-            };
-
-            stab = Some(Stability {
-                level: level,
-                feature: feature.unwrap_or(intern_and_get_ident("bogus")),
-                since: since,
-                deprecated_since: None,
-                reason: reason,
-                issue: issue,
-            });
-        } else { // "deprecated"
-            if deprecated.is_some() {
-                diagnostic.span_err(item_sp, "multiple deprecated attributes");
             }
-
-            deprecated = Some((since, reason));
+        } else {
+            diagnostic.span_err(attr.span(), "incorrect stability attribute type");
+            continue
         }
     }
 
     // Merge the deprecation info into the stability info
-    if deprecated.is_some() {
-        match stab {
-            Some(ref mut s) => {
-                let (since, reason) = deprecated.unwrap();
-                s.deprecated_since = since;
-                s.reason = reason;
-            }
-            None => {
-                diagnostic.span_err(item_sp, "deprecated attribute must be paired with \
-                                              either stable or unstable attribute");
+    if let Some(depr) = depr {
+        if let Some(ref mut stab) = stab {
+            if let Unstable {reason: ref mut reason @ None, ..} = stab.level {
+                *reason = Some(depr.reason.clone())
             }
+            stab.depr = Some(depr);
+        } else {
+            diagnostic.span_err(item_sp, "deprecated attribute must be paired with \
+                                          either stable or unstable attribute");
         }
-    } else if stab.as_ref().map_or(false, |s| s.level == Unstable && s.issue.is_none()) {
-        // non-deprecated unstable items need to point to issues.
-        diagnostic.span_err(item_sp,
-                            "non-deprecated unstable items need to point \
-                             to an issue with `issue = \"NNN\"`");
     }
 
-    (stab, used_attrs)
+    stab
 }
 
 /// Find the first stability attribute. `None` if none exists.
 pub fn find_stability(diagnostic: &SpanHandler, attrs: &[Attribute],
                       item_sp: Span) -> Option<Stability> {
-    let (s, used) = find_stability_generic(diagnostic, attrs.iter(), item_sp);
-    for used in used { mark_used(used) }
-    return s;
+    find_stability_generic(diagnostic, attrs.iter(), item_sp)
 }
 
 pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[P<MetaItem>]) {
index 56a15ce895cf24f7fddc0cfd75f6e4e273b3095e..a73fd4534c96cc142398d9f0bda62e1e62b517fb 100644 (file)
@@ -29,7 +29,6 @@ use std::io::{self, Read};
 
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 
-use parse::token::intern;
 use ast::Name;
 
 // _____________________________________________________________________________
@@ -142,6 +141,10 @@ impl Span {
     pub fn substitute_dummy(self, other: Span) -> Span {
         if self == DUMMY_SP { other } else { self }
     }
+
+    pub fn contains(self, other: Span) -> bool {
+        self.lo <= other.lo && other.hi <= self.hi
+    }
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
@@ -265,28 +268,8 @@ pub enum ExpnFormat {
     MacroAttribute(Name),
     /// e.g. `format!()`
     MacroBang(Name),
-    /// Syntax sugar expansion performed by the compiler (libsyntax::expand).
-    CompilerExpansion(CompilerExpansionFormat),
-}
-
-#[derive(Clone, Copy, Hash, Debug, PartialEq, Eq)]
-pub enum CompilerExpansionFormat {
-    IfLet,
-    PlacementIn,
-    WhileLet,
-    ForLoop,
 }
 
-impl CompilerExpansionFormat {
-    pub fn name(self) -> &'static str {
-        match self {
-            CompilerExpansionFormat::IfLet => "if let expansion",
-            CompilerExpansionFormat::PlacementIn => "placement-in expansion",
-            CompilerExpansionFormat::WhileLet => "while let expansion",
-            CompilerExpansionFormat::ForLoop => "for loop expansion",
-        }
-    }
-}
 #[derive(Clone, Hash, Debug)]
 pub struct NameAndSpan {
     /// The format with which the macro was invoked.
@@ -306,7 +289,6 @@ impl NameAndSpan {
         match self.format {
             ExpnFormat::MacroAttribute(s) => s,
             ExpnFormat::MacroBang(s) => s,
-            ExpnFormat::CompilerExpansion(ce) => intern(ce.name()),
         }
     }
 }
@@ -1011,7 +993,7 @@ impl CodeMap {
 
                     let span_comes_from_this_expansion =
                         info.callee.span.map_or(span == info.call_site, |mac_span| {
-                            mac_span.lo <= span.lo && span.hi <= mac_span.hi
+                            mac_span.contains(span)
                         });
 
                     debug!("span_allows_unstable: span: {:?} call_site: {:?} callee: {:?}",
@@ -1083,7 +1065,6 @@ pub struct MalformedCodemapPositions {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use std::rc::Rc;
 
     #[test]
     fn t1 () {
index faf0b51c8de0eda798c088a140ed32b2c880ac73..aa674bdbcf3a4d6db4c184abd462b9c7de532eef 100644 (file)
@@ -140,21 +140,14 @@ fn fold_item_underscore<F>(cx: &mut Context<F>, item: ast::Item_) -> ast::Item_
                 if !(cx.in_cfg)(&v.node.attrs) {
                     None
                 } else {
-                    Some(v.map(|Spanned {node: ast::Variant_ {id, name, attrs, kind,
-                                                              disr_expr, vis}, span}| {
+                    Some(v.map(|Spanned {node: ast::Variant_ {name, attrs, data,
+                                                              disr_expr}, span}| {
                         Spanned {
                             node: ast::Variant_ {
-                                id: id,
                                 name: name,
                                 attrs: attrs,
-                                kind: match kind {
-                                    ast::TupleVariantKind(..) => kind,
-                                    ast::StructVariantKind(def) => {
-                                        ast::StructVariantKind(fold_struct(cx, def))
-                                    }
-                                },
+                                data: fold_struct(cx, data),
                                 disr_expr: disr_expr,
-                                vis: vis
                             },
                             span: span
                         }
@@ -171,17 +164,22 @@ fn fold_item_underscore<F>(cx: &mut Context<F>, item: ast::Item_) -> ast::Item_
     fold::noop_fold_item_underscore(item, cx)
 }
 
-fn fold_struct<F>(cx: &mut Context<F>, def: P<ast::StructDef>) -> P<ast::StructDef> where
+fn fold_struct<F>(cx: &mut Context<F>, vdata: ast::VariantData) -> ast::VariantData where
     F: FnMut(&[ast::Attribute]) -> bool
 {
-    def.map(|ast::StructDef { fields, ctor_id }| {
-        ast::StructDef {
-            fields: fields.into_iter().filter(|m| {
+    match vdata {
+        ast::VariantData::Struct(fields, id) => {
+            ast::VariantData::Struct(fields.into_iter().filter(|m| {
                 (cx.in_cfg)(&m.node.attrs)
-            }).collect(),
-            ctor_id: ctor_id,
+            }).collect(), id)
         }
-    })
+        ast::VariantData::Tuple(fields, id) => {
+            ast::VariantData::Tuple(fields.into_iter().filter(|m| {
+                (cx.in_cfg)(&m.node.attrs)
+            }).collect(), id)
+        }
+        ast::VariantData::Unit(id) => ast::VariantData::Unit(id)
+    }
 }
 
 fn retain_stmt<F>(cx: &mut Context<F>, stmt: &ast::Stmt) -> bool where
@@ -226,10 +224,10 @@ fn fold_expr<F>(cx: &mut Context<F>, expr: P<ast::Expr>) -> P<ast::Expr> where
         fold::noop_fold_expr(ast::Expr {
             id: id,
             node: match node {
-                ast::ExprMatch(m, arms, source) => {
+                ast::ExprMatch(m, arms) => {
                     ast::ExprMatch(m, arms.into_iter()
                                         .filter(|a| (cx.in_cfg)(&a.attrs))
-                                        .collect(), source)
+                                        .collect())
                 }
                 _ => node
             },
index c177eb1f00bbd39fe7e994b67f79180f9ec998b5..2a8cdf138b0e6fad127e06180fe12e87c85387d4 100644 (file)
@@ -737,7 +737,6 @@ impl EmitterWriter {
                         let (pre, post) = match ei.callee.format {
                             codemap::MacroAttribute(..) => ("#[", "]"),
                             codemap::MacroBang(..) => ("", "!"),
-                            codemap::CompilerExpansion(..) => ("", ""),
                         };
                         // Don't print recursive invocations
                         if ei.call_site != last_span {
@@ -842,7 +841,7 @@ pub fn expect<T, M>(diag: &SpanHandler, opt: Option<T>, msg: M) -> T where
 #[cfg(test)]
 mod test {
     use super::{EmitterWriter, Level};
-    use codemap::{mk_sp, CodeMap, BytePos};
+    use codemap::{mk_sp, CodeMap};
     use std::sync::{Arc, Mutex};
     use std::io::{self, Write};
     use std::str::from_utf8;
index 6c3bee3f48ed9c90fe71abd9a3fd236f9c950e90..a276765e2161692ab636ec3ea164ad443219b32e 100644 (file)
@@ -138,7 +138,7 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt,
             ));
         }
     });
-    let sym = Ident::new(token::gensym(&format!(
+    let sym = Ident::with_empty_ctxt(token::gensym(&format!(
         "__register_diagnostic_{}", code
     )));
     MacEager::items(SmallVector::many(vec![
index 2b4df3186de6bc99629189e254d616d51a308857..ddc4443a77c9d7aa290aeb0511613560de3d5179 100644 (file)
@@ -28,7 +28,7 @@ pub fn entry_point_type(item: &Item, depth: usize) -> EntryPointType {
                 EntryPointType::Start
             } else if attr::contains_name(&item.attrs, "main") {
                 EntryPointType::MainAttr
-            } else if item.ident.name == "main" {
+            } else if item.ident.name.as_str() == "main" {
                 if depth == 1 {
                     // This is a top-level function so can be 'main'
                     EntryPointType::MainNamed
index f1aa8139ec1df3a8b0abfde52cdc0450297298ae..d2b416f54157332b030a4bc94b43ec3305c39094 100644 (file)
@@ -22,6 +22,7 @@ use feature_gate;
 use parse::token::{intern, InternedString};
 use parse::token;
 use ptr::P;
+use syntax::ast::AsmDialect;
 
 enum State {
     Asm,
@@ -65,7 +66,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     let mut clobs = Vec::new();
     let mut volatile = false;
     let mut alignstack = false;
-    let mut dialect = ast::AsmAtt;
+    let mut dialect = AsmDialect::Att;
 
     let mut state = Asm;
 
@@ -178,7 +179,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                 } else if option == "alignstack" {
                     alignstack = true;
                 } else if option == "intel" {
-                    dialect = ast::AsmIntel;
+                    dialect = AsmDialect::Intel;
                 } else {
                     cx.span_warn(p.last_span, "unrecognized option");
                 }
index 775d47a8c0e087fc782e66479de426fd6a51bd84..a248f839d73295979f3f47efb6a9997fb030bad7 100644 (file)
@@ -13,7 +13,7 @@ pub use self::SyntaxExtension::*;
 use ast;
 use ast::Name;
 use codemap;
-use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION, CompilerExpansion};
+use codemap::{CodeMap, Span, ExpnId, ExpnInfo, NO_EXPANSION};
 use ext;
 use ext::expand;
 use ext::tt::macro_rules;
@@ -544,12 +544,6 @@ fn initial_syntax_expander_table<'feat>(ecfg: &expand::ExpansionConfig<'feat>)
     syntax_expanders.insert(intern("cfg"),
                             builtin_normal_expander(
                                     ext::cfg::expand_cfg));
-    syntax_expanders.insert(intern("push_unsafe"),
-                            builtin_normal_expander(
-                                ext::pushpop_safe::expand_push_unsafe));
-    syntax_expanders.insert(intern("pop_unsafe"),
-                            builtin_normal_expander(
-                                ext::pushpop_safe::expand_pop_unsafe));
     syntax_expanders.insert(intern("trace_macros"),
                             builtin_normal_expander(
                                     ext::trace_macros::expand_trace_macros));
@@ -593,14 +587,14 @@ impl<'a> ExtCtxt<'a> {
         }
     }
 
-    #[unstable(feature = "rustc_private")]
+    #[unstable(feature = "rustc_private", issue = "0")]
     #[deprecated(since = "1.0.0",
                  reason = "Replaced with `expander().fold_expr()`")]
     pub fn expand_expr(&mut self, e: P<ast::Expr>) -> P<ast::Expr> {
         self.expander().fold_expr(e)
     }
 
-    /// Returns a `Folder` for deeply expanding all macros in a AST node.
+    /// Returns a `Folder` for deeply expanding all macros in an AST node.
     pub fn expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> {
         expand::MacroExpander::new(self)
     }
@@ -646,15 +640,12 @@ impl<'a> ExtCtxt<'a> {
         loop {
             if self.codemap().with_expn_info(expn_id, |info| {
                 info.map_or(None, |i| {
-                    if i.callee.name() == "include" {
+                    if i.callee.name().as_str() == "include" {
                         // Stop going up the backtrace once include! is encountered
                         return None;
                     }
                     expn_id = i.call_site.expn_id;
-                    match i.callee.format {
-                        CompilerExpansion(..) => (),
-                        _ => last_macro = Some(i.call_site),
-                    }
+                    last_macro = Some(i.call_site);
                     return Some(());
                 })
             }).is_none() {
@@ -899,9 +890,9 @@ impl SyntaxEnv {
         unreachable!()
     }
 
-    pub fn find(&self, k: &Name) -> Option<Rc<SyntaxExtension>> {
+    pub fn find(&self, k: Name) -> Option<Rc<SyntaxExtension>> {
         for frame in self.chain.iter().rev() {
-            match frame.map.get(k) {
+            match frame.map.get(&k) {
                 Some(v) => return Some(v.clone()),
                 None => {}
             }
index 771ac85ef19210bff535ed753fb9b4265ec2b37c..16a5eb05c4b5f780f083535cc798af1202e6d0e9 100644 (file)
@@ -73,7 +73,6 @@ pub trait AstBuilder {
 
     fn ty_vars(&self, ty_params: &OwnedSlice<ast::TyParam>) -> Vec<P<ast::Ty>> ;
     fn ty_vars_global(&self, ty_params: &OwnedSlice<ast::TyParam>) -> Vec<P<ast::Ty>> ;
-    fn ty_field_imm(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> ast::TypeField;
 
     fn typaram(&self,
                span: Span,
@@ -248,9 +247,9 @@ pub trait AstBuilder {
     fn item_struct_poly(&self,
                         span: Span,
                         name: Ident,
-                        struct_def: ast::StructDef,
+                        struct_def: ast::VariantData,
                         generics: Generics) -> P<ast::Item>;
-    fn item_struct(&self, span: Span, name: Ident, struct_def: ast::StructDef) -> P<ast::Item>;
+    fn item_struct(&self, span: Span, name: Ident, struct_def: ast::VariantData) -> P<ast::Item>;
 
     fn item_mod(&self, span: Span, inner_span: Span,
                 name: Ident, attrs: Vec<ast::Attribute>,
@@ -443,14 +442,6 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                           Vec::new()))
     }
 
-    fn ty_field_imm(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> ast::TypeField {
-        ast::TypeField {
-            ident: name,
-            mt: ast::MutTy { ty: ty, mutbl: ast::MutImmutable },
-            span: span,
-        }
-    }
-
     fn ty_infer(&self, span: Span) -> P<ast::Ty> {
         self.ty(span, ast::TyInfer)
     }
@@ -877,7 +868,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     }
 
     fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: Vec<ast::Arm>) -> P<Expr> {
-        self.expr(span, ast::ExprMatch(arg, arms, ast::MatchSource::Normal))
+        self.expr(span, ast::ExprMatch(arg, arms))
     }
 
     fn expr_if(&self, span: Span, cond: P<ast::Expr>,
@@ -1002,18 +993,27 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     }
 
     fn variant(&self, span: Span, name: Ident, tys: Vec<P<ast::Ty>> ) -> ast::Variant {
-        let args = tys.into_iter().map(|ty| {
-            ast::VariantArg { ty: ty, id: ast::DUMMY_NODE_ID }
+        let fields: Vec<_> = tys.into_iter().map(|ty| {
+            Spanned { span: ty.span, node: ast::StructField_ {
+                ty: ty,
+                kind: ast::UnnamedField(ast::Inherited),
+                attrs: Vec::new(),
+                id: ast::DUMMY_NODE_ID,
+            }}
         }).collect();
 
+        let vdata = if fields.is_empty() {
+            ast::VariantData::Unit(ast::DUMMY_NODE_ID)
+        } else {
+            ast::VariantData::Tuple(fields, ast::DUMMY_NODE_ID)
+        };
+
         respan(span,
                ast::Variant_ {
                    name: name,
                    attrs: Vec::new(),
-                   kind: ast::TupleVariantKind(args),
-                   id: ast::DUMMY_NODE_ID,
+                   data: vdata,
                    disr_expr: None,
-                   vis: ast::Public
                })
     }
 
@@ -1030,7 +1030,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     }
 
     fn item_struct(&self, span: Span, name: Ident,
-                   struct_def: ast::StructDef) -> P<ast::Item> {
+                   struct_def: ast::VariantData) -> P<ast::Item> {
         self.item_struct_poly(
             span,
             name,
@@ -1040,8 +1040,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     }
 
     fn item_struct_poly(&self, span: Span, name: Ident,
-        struct_def: ast::StructDef, generics: Generics) -> P<ast::Item> {
-        self.item(span, name, Vec::new(), ast::ItemStruct(P(struct_def), generics))
+        struct_def: ast::VariantData, generics: Generics) -> P<ast::Item> {
+        self.item(span, name, Vec::new(), ast::ItemStruct(struct_def, generics))
     }
 
     fn item_mod(&self, span: Span, inner_span: Span, name: Ident,
@@ -1089,7 +1089,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
     fn attribute(&self, sp: Span, mi: P<ast::MetaItem>) -> ast::Attribute {
         respan(sp, ast::Attribute_ {
             id: attr::mk_attr_id(),
-            style: ast::AttrOuter,
+            style: ast::AttrStyle::Outer,
             value: mi,
             is_sugared_doc: false,
         })
diff --git a/src/libsyntax/ext/deriving/debug.rs b/src/libsyntax/ext/deriving/debug.rs
new file mode 100644 (file)
index 0000000..537375f
--- /dev/null
@@ -0,0 +1,126 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ast;
+use ast::{MetaItem, Expr,};
+use codemap::Span;
+use ext::base::{ExtCtxt, Annotatable};
+use ext::build::AstBuilder;
+use ext::deriving::generic::*;
+use ext::deriving::generic::ty::*;
+use parse::token;
+use ptr::P;
+
+pub fn expand_deriving_debug(cx: &mut ExtCtxt,
+                            span: Span,
+                            mitem: &MetaItem,
+                            item: &Annotatable,
+                            push: &mut FnMut(Annotatable))
+{
+    // &mut ::std::fmt::Formatter
+    let fmtr = Ptr(Box::new(Literal(path_std!(cx, core::fmt::Formatter))),
+                   Borrowed(None, ast::MutMutable));
+
+    let trait_def = TraitDef {
+        span: span,
+        attributes: Vec::new(),
+        path: path_std!(cx, core::fmt::Debug),
+        additional_bounds: Vec::new(),
+        generics: LifetimeBounds::empty(),
+        is_unsafe: false,
+        methods: vec![
+            MethodDef {
+                name: "fmt",
+                generics: LifetimeBounds::empty(),
+                explicit_self: borrowed_explicit_self(),
+                args: vec!(fmtr),
+                ret_ty: Literal(path_std!(cx, core::fmt::Result)),
+                attributes: Vec::new(),
+                is_unsafe: false,
+                combine_substructure: combine_substructure(Box::new(|a, b, c| {
+                    show_substructure(a, b, c)
+                }))
+            }
+        ],
+        associated_types: Vec::new(),
+    };
+    trait_def.expand(cx, mitem, item, push)
+}
+
+/// We use the debug builders to do the heavy lifting here
+fn show_substructure(cx: &mut ExtCtxt, span: Span,
+                     substr: &Substructure) -> P<Expr> {
+    // build fmt.debug_struct(<name>).field(<fieldname>, &<fieldval>)....build()
+    // or fmt.debug_tuple(<name>).field(&<fieldval>)....build()
+    // based on the "shape".
+    let ident = match *substr.fields {
+        Struct(_) => substr.type_ident,
+        EnumMatching(_, v, _) => v.node.name,
+        EnumNonMatchingCollapsed(..) | StaticStruct(..) | StaticEnum(..) => {
+            cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`")
+        }
+    };
+
+    // We want to make sure we have the expn_id set so that we can use unstable methods
+    let span = Span { expn_id: cx.backtrace(), .. span };
+    let name = cx.expr_lit(span, ast::Lit_::LitStr(ident.name.as_str(),
+                                                   ast::StrStyle::CookedStr));
+    let mut expr = substr.nonself_args[0].clone();
+
+    match *substr.fields {
+        Struct(ref fields) | EnumMatching(_, _, ref fields) => {
+
+            if fields.is_empty() || fields[0].name.is_none() {
+                // tuple struct/"normal" variant
+                expr = cx.expr_method_call(span,
+                                           expr,
+                                           token::str_to_ident("debug_tuple"),
+                                           vec![name]);
+
+                for field in fields {
+                    // Use double indirection to make sure this works for unsized types
+                    let field = cx.expr_addr_of(field.span, field.self_.clone());
+                    let field = cx.expr_addr_of(field.span, field);
+
+                    expr = cx.expr_method_call(span,
+                                               expr,
+                                               token::str_to_ident("field"),
+                                               vec![field]);
+                }
+            } else {
+                // normal struct/struct variant
+                expr = cx.expr_method_call(span,
+                                           expr,
+                                           token::str_to_ident("debug_struct"),
+                                           vec![name]);
+
+                for field in fields {
+                    let name = cx.expr_lit(field.span, ast::Lit_::LitStr(
+                            field.name.unwrap().name.as_str(),
+                            ast::StrStyle::CookedStr));
+
+                    // Use double indirection to make sure this works for unsized types
+                    let field = cx.expr_addr_of(field.span, field.self_.clone());
+                    let field = cx.expr_addr_of(field.span, field);
+                    expr = cx.expr_method_call(span,
+                                               expr,
+                                               token::str_to_ident("field"),
+                                               vec![name, field]);
+                }
+            }
+        }
+        _ => unreachable!()
+    }
+
+    cx.expr_method_call(span,
+                        expr,
+                        token::str_to_ident("finish"),
+                        vec![])
+}
index 9fc2745cf929a568b1db266ecebad403932796e2..5c6e2fce8adcea845f8ddb607608648c9b622476 100644 (file)
 //! A static method on the types above would result in,
 //!
 //! ```{.text}
-//! StaticStruct(<ast::StructDef of A>, Named(vec![(<ident of x>, <span of x>)]))
+//! StaticStruct(<ast::VariantData of A>, Named(vec![(<ident of x>, <span of x>)]))
 //!
-//! StaticStruct(<ast::StructDef of B>, Unnamed(vec![<span of x>]))
+//! StaticStruct(<ast::VariantData of B>, Unnamed(vec![<span of x>]))
 //!
 //! StaticEnum(<ast::EnumDef of C>,
 //!            vec![(<ident of C0>, <span of C0>, Unnamed(vec![<span of i32>])),
@@ -194,7 +194,7 @@ use std::vec;
 use abi::Abi;
 use abi;
 use ast;
-use ast::{EnumDef, Expr, Ident, Generics, StructDef};
+use ast::{EnumDef, Expr, Ident, Generics, VariantData};
 use ast_util;
 use attr;
 use attr::AttrMetaMethods;
@@ -317,7 +317,7 @@ pub enum SubstructureFields<'a> {
     EnumNonMatchingCollapsed(Vec<Ident>, &'a [P<ast::Variant>], &'a [Ident]),
 
     /// A static method where `Self` is a struct.
-    StaticStruct(&'a ast::StructDef, StaticFields),
+    StaticStruct(&'a ast::VariantData, StaticFields),
     /// A static method where `Self` is an enum.
     StaticEnum(&'a ast::EnumDef, Vec<(Ident, Span, StaticFields)>),
 }
@@ -417,7 +417,7 @@ impl<'a> TraitDef<'a> {
                 let mut attrs = newitem.attrs.clone();
                 attrs.extend(item.attrs.iter().filter(|a| {
                     match &a.name()[..] {
-                        "allow" | "warn" | "deny" | "forbid" => true,
+                        "allow" | "warn" | "deny" | "forbid" | "stable" | "unstable" => true,
                         _ => false,
                     }
                 }).cloned());
@@ -649,10 +649,10 @@ impl<'a> TraitDef<'a> {
 
     fn expand_struct_def(&self,
                          cx: &mut ExtCtxt,
-                         struct_def: &'a StructDef,
+                         struct_def: &'a VariantData,
                          type_ident: Ident,
                          generics: &Generics) -> P<ast::Item> {
-        let field_tys: Vec<P<ast::Ty>> = struct_def.fields.iter()
+        let field_tys: Vec<P<ast::Ty>> = struct_def.fields().iter()
             .map(|field| field.node.ty.clone())
             .collect();
 
@@ -700,16 +700,8 @@ impl<'a> TraitDef<'a> {
         let mut field_tys = Vec::new();
 
         for variant in &enum_def.variants {
-            match variant.node.kind {
-                ast::VariantKind::TupleVariantKind(ref args) => {
-                    field_tys.extend(args.iter()
-                        .map(|arg| arg.ty.clone()));
-                }
-                ast::VariantKind::StructVariantKind(ref args) => {
-                    field_tys.extend(args.fields.iter()
-                        .map(|field| field.node.ty.clone()));
-                }
-            }
+            field_tys.extend(variant.node.data.fields().iter()
+                .map(|field| field.node.ty.clone()));
         }
 
         let methods = self.methods.iter().map(|method_def| {
@@ -935,7 +927,7 @@ impl<'a> MethodDef<'a> {
     fn expand_struct_method_body<'b>(&self,
                                  cx: &mut ExtCtxt,
                                  trait_: &TraitDef<'b>,
-                                 struct_def: &'b StructDef,
+                                 struct_def: &'b VariantData,
                                  type_ident: Ident,
                                  self_args: &[P<Expr>],
                                  nonself_args: &[P<Expr>])
@@ -1004,7 +996,7 @@ impl<'a> MethodDef<'a> {
     fn expand_static_struct_method_body(&self,
                                         cx: &mut ExtCtxt,
                                         trait_: &TraitDef,
-                                        struct_def: &StructDef,
+                                        struct_def: &VariantData,
                                         type_ident: Ident,
                                         self_args: &[P<Expr>],
                                         nonself_args: &[P<Expr>])
@@ -1413,14 +1405,7 @@ impl<'a> MethodDef<'a> {
         -> P<Expr> {
         let summary = enum_def.variants.iter().map(|v| {
             let ident = v.node.name;
-            let summary = match v.node.kind {
-                ast::TupleVariantKind(ref args) => {
-                    Unnamed(args.iter().map(|va| trait_.set_expn_info(cx, va.ty.span)).collect())
-                }
-                ast::StructVariantKind(ref struct_def) => {
-                    trait_.summarise_struct(cx, &**struct_def)
-                }
-            };
+            let summary = trait_.summarise_struct(cx, &v.node.data);
             (ident, v.span, summary)
         }).collect();
         self.call_substructure_method(cx, trait_, type_ident,
@@ -1456,10 +1441,10 @@ impl<'a> TraitDef<'a> {
 
     fn summarise_struct(&self,
                         cx: &mut ExtCtxt,
-                        struct_def: &StructDef) -> StaticFields {
+                        struct_def: &VariantData) -> StaticFields {
         let mut named_idents = Vec::new();
         let mut just_spans = Vec::new();
-        for field in struct_def.fields.iter(){
+        for field in struct_def.fields(){
             let sp = self.set_expn_info(cx, field.span);
             match field.node.kind {
                 ast::NamedField(ident, _) => named_idents.push((ident, sp)),
@@ -1492,13 +1477,13 @@ impl<'a> TraitDef<'a> {
     fn create_struct_pattern(&self,
                              cx: &mut ExtCtxt,
                              struct_path: ast::Path,
-                             struct_def: &'a StructDef,
+                             struct_def: &'a VariantData,
                              prefix: &str,
                              mutbl: ast::Mutability)
                              -> (P<ast::Pat>, Vec<(Span, Option<Ident>,
                                                    P<Expr>,
                                                    &'a [ast::Attribute])>) {
-        if struct_def.fields.is_empty() {
+        if struct_def.fields().is_empty() {
             return (cx.pat_enum(self.span, struct_path, vec![]), vec![]);
         }
 
@@ -1506,7 +1491,7 @@ impl<'a> TraitDef<'a> {
         let mut ident_expr = Vec::new();
         let mut struct_type = Unknown;
 
-        for (i, struct_field) in struct_def.fields.iter().enumerate() {
+        for (i, struct_field) in struct_def.fields().iter().enumerate() {
             let sp = self.set_expn_info(cx, struct_field.span);
             let opt_id = match struct_field.node.kind {
                 ast::NamedField(ident, _) if (struct_type == Unknown ||
@@ -1560,34 +1545,7 @@ impl<'a> TraitDef<'a> {
         -> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>, &'a [ast::Attribute])>) {
         let variant_ident = variant.node.name;
         let variant_path = cx.path(variant.span, vec![enum_ident, variant_ident]);
-        match variant.node.kind {
-            ast::TupleVariantKind(ref variant_args) => {
-                if variant_args.is_empty() {
-                    return (cx.pat_enum(variant.span, variant_path, vec![]), vec![]);
-                }
-
-                let mut paths = Vec::new();
-                let mut ident_expr: Vec<(_, _, _, &'a [ast::Attribute])> = Vec::new();
-                for (i, va) in variant_args.iter().enumerate() {
-                    let sp = self.set_expn_info(cx, va.ty.span);
-                    let ident = cx.ident_of(&format!("{}_{}", prefix, i));
-                    let path1 = codemap::Spanned{span: sp, node: ident};
-                    paths.push(path1);
-                    let expr_path = cx.expr_path(cx.path_ident(sp, ident));
-                    let val = cx.expr(sp, ast::ExprParen(cx.expr_deref(sp, expr_path)));
-                    ident_expr.push((sp, None, val, &[]));
-                }
-
-                let subpats = self.create_subpatterns(cx, paths, mutbl);
-
-                (cx.pat_enum(variant.span, variant_path, subpats),
-                 ident_expr)
-            }
-            ast::StructVariantKind(ref struct_def) => {
-                self.create_struct_pattern(cx, variant_path, &**struct_def,
-                                           prefix, mutbl)
-            }
-        }
+        self.create_struct_pattern(cx, variant_path, &variant.node.data, prefix, mutbl)
     }
 }
 
index c7f582854aeef0dd034fc1be93741fdec39e1967..d26bb794c88b9453d67d201b5c8c3e70ace6294d 100644 (file)
@@ -60,7 +60,7 @@ pub mod clone;
 pub mod encodable;
 pub mod decodable;
 pub mod hash;
-pub mod show;
+pub mod debug;
 pub mod default;
 pub mod primitive;
 
@@ -173,7 +173,7 @@ derive_traits! {
     "PartialOrd" => partial_ord::expand_deriving_partial_ord,
     "Ord" => ord::expand_deriving_ord,
 
-    "Debug" => show::expand_deriving_show,
+    "Debug" => debug::expand_deriving_debug,
 
     "Default" => default::expand_deriving_default,
 
@@ -184,7 +184,6 @@ derive_traits! {
     "Copy" => bounds::expand_deriving_copy,
 
     // deprecated
-    "Show" => show::expand_deriving_show,
     "Encodable" => encodable::expand_deriving_encodable,
     "Decodable" => decodable::expand_deriving_decodable,
 }
@@ -192,7 +191,6 @@ derive_traits! {
 #[inline] // because `name` is a compile-time constant
 fn warn_if_deprecated(ecx: &mut ExtCtxt, sp: Span, name: &str) {
     if let Some(replacement) = match name {
-        "Show" => Some("Debug"),
         "Encodable" => Some("RustcEncodable"),
         "Decodable" => Some("RustcDecodable"),
         _ => None,
index 5d3cc50557cde8445fe6b3c14c411275b23e5590..07b587783583e699d1bd6e0c5187999100aa172f 100644 (file)
@@ -94,45 +94,35 @@ fn cs_from(name: &str, cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure
             let mut arms = Vec::new();
 
             for variant in &enum_def.variants {
-                match variant.node.kind {
-                    ast::TupleVariantKind(ref args) => {
-                        if !args.is_empty() {
-                            cx.span_err(trait_span,
-                                        "`FromPrimitive` cannot be derived for \
-                                        enum variants with arguments");
-                            return cx.expr_fail(trait_span,
-                                                InternedString::new(""));
-                        }
-                        let span = variant.span;
+                let def = &variant.node.data;
+                if !def.is_unit() {
+                    cx.span_err(trait_span, "`FromPrimitive` cannot be derived \
+                                             for enums with non-unit variants");
+                    return cx.expr_fail(trait_span,
+                                        InternedString::new(""));
+                }
 
-                        // expr for `$n == $variant as $name`
-                        let path = cx.path(span, vec![substr.type_ident, variant.node.name]);
-                        let variant = cx.expr_path(path);
-                        let ty = cx.ty_ident(span, cx.ident_of(name));
-                        let cast = cx.expr_cast(span, variant.clone(), ty);
-                        let guard = cx.expr_binary(span, ast::BiEq, n.clone(), cast);
+                let span = variant.span;
 
-                        // expr for `Some($variant)`
-                        let body = cx.expr_some(span, variant);
+                // expr for `$n == $variant as $name`
+                let path = cx.path(span, vec![substr.type_ident, variant.node.name]);
+                let variant = cx.expr_path(path);
+                let ty = cx.ty_ident(span, cx.ident_of(name));
+                let cast = cx.expr_cast(span, variant.clone(), ty);
+                let guard = cx.expr_binary(span, ast::BiEq, n.clone(), cast);
 
-                        // arm for `_ if $guard => $body`
-                        let arm = ast::Arm {
-                            attrs: vec!(),
-                            pats: vec!(cx.pat_wild(span)),
-                            guard: Some(guard),
-                            body: body,
-                        };
+                // expr for `Some($variant)`
+                let body = cx.expr_some(span, variant);
 
-                        arms.push(arm);
-                    }
-                    ast::StructVariantKind(_) => {
-                        cx.span_err(trait_span,
-                                    "`FromPrimitive` cannot be derived for enums \
-                                    with struct variants");
-                        return cx.expr_fail(trait_span,
-                                            InternedString::new(""));
-                    }
-                }
+                // arm for `_ if $guard => $body`
+                let arm = ast::Arm {
+                    attrs: vec!(),
+                    pats: vec!(cx.pat_wild(span)),
+                    guard: Some(guard),
+                    body: body,
+                };
+
+                arms.push(arm);
             }
 
             // arm for `_ => None`
diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs
deleted file mode 100644 (file)
index 4d70ca1..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use ast;
-use ast::{MetaItem, Expr,};
-use codemap::Span;
-use ext::base::{ExtCtxt, Annotatable};
-use ext::build::AstBuilder;
-use ext::deriving::generic::*;
-use ext::deriving::generic::ty::*;
-use parse::token;
-use ptr::P;
-
-pub fn expand_deriving_show(cx: &mut ExtCtxt,
-                            span: Span,
-                            mitem: &MetaItem,
-                            item: &Annotatable,
-                            push: &mut FnMut(Annotatable))
-{
-    // &mut ::std::fmt::Formatter
-    let fmtr = Ptr(Box::new(Literal(path_std!(cx, core::fmt::Formatter))),
-                   Borrowed(None, ast::MutMutable));
-
-    let trait_def = TraitDef {
-        span: span,
-        attributes: Vec::new(),
-        path: path_std!(cx, core::fmt::Debug),
-        additional_bounds: Vec::new(),
-        generics: LifetimeBounds::empty(),
-        is_unsafe: false,
-        methods: vec![
-            MethodDef {
-                name: "fmt",
-                generics: LifetimeBounds::empty(),
-                explicit_self: borrowed_explicit_self(),
-                args: vec!(fmtr),
-                ret_ty: Literal(path_std!(cx, core::fmt::Result)),
-                attributes: Vec::new(),
-                is_unsafe: false,
-                combine_substructure: combine_substructure(Box::new(|a, b, c| {
-                    show_substructure(a, b, c)
-                }))
-            }
-        ],
-        associated_types: Vec::new(),
-    };
-    trait_def.expand(cx, mitem, item, push)
-}
-
-/// We use the debug builders to do the heavy lifting here
-fn show_substructure(cx: &mut ExtCtxt, span: Span,
-                     substr: &Substructure) -> P<Expr> {
-    // build fmt.debug_struct(<name>).field(<fieldname>, &<fieldval>)....build()
-    // or fmt.debug_tuple(<name>).field(&<fieldval>)....build()
-    // based on the "shape".
-    let ident = match *substr.fields {
-        Struct(_) => substr.type_ident,
-        EnumMatching(_, v, _) => v.node.name,
-        EnumNonMatchingCollapsed(..) | StaticStruct(..) | StaticEnum(..) => {
-            cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`")
-        }
-    };
-
-    // We want to make sure we have the expn_id set so that we can use unstable methods
-    let span = Span { expn_id: cx.backtrace(), .. span };
-    let name = cx.expr_lit(span, ast::Lit_::LitStr(ident.name.as_str(),
-                                                   ast::StrStyle::CookedStr));
-    let mut expr = substr.nonself_args[0].clone();
-
-    match *substr.fields {
-        Struct(ref fields) | EnumMatching(_, _, ref fields) => {
-
-            if fields.is_empty() || fields[0].name.is_none() {
-                // tuple struct/"normal" variant
-                expr = cx.expr_method_call(span,
-                                           expr,
-                                           token::str_to_ident("debug_tuple"),
-                                           vec![name]);
-
-                for field in fields {
-                    // Use double indirection to make sure this works for unsized types
-                    let field = cx.expr_addr_of(field.span, field.self_.clone());
-                    let field = cx.expr_addr_of(field.span, field);
-
-                    expr = cx.expr_method_call(span,
-                                               expr,
-                                               token::str_to_ident("field"),
-                                               vec![field]);
-                }
-            } else {
-                // normal struct/struct variant
-                expr = cx.expr_method_call(span,
-                                           expr,
-                                           token::str_to_ident("debug_struct"),
-                                           vec![name]);
-
-                for field in fields {
-                    let name = cx.expr_lit(field.span, ast::Lit_::LitStr(
-                            field.name.unwrap().name.as_str(),
-                            ast::StrStyle::CookedStr));
-
-                    // Use double indirection to make sure this works for unsized types
-                    let field = cx.expr_addr_of(field.span, field.self_.clone());
-                    let field = cx.expr_addr_of(field.span, field);
-                    expr = cx.expr_method_call(span,
-                                               expr,
-                                               token::str_to_ident("field"),
-                                               vec![name, field]);
-                }
-            }
-        }
-        _ => unreachable!()
-    }
-
-    cx.expr_method_call(span,
-                        expr,
-                        token::str_to_ident("finish"),
-                        vec![])
-}
index 1991124ae2671bfc72a48be42c2788cbb6afa742..b1b4605d5ec6573b9702479f4847174ac9dc23cd 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use ast::{Block, Crate, DeclLocal, ExprMac, PatMac};
-use ast::{Local, Ident, MacInvocTT};
+use ast::{Local, Ident, Mac_};
 use ast::{ItemMac, MacStmtWithSemicolon, Mrk, Stmt, StmtDecl, StmtMac};
 use ast::{StmtExpr, StmtSemi};
 use ast::TokenTree;
@@ -20,53 +20,20 @@ use attr;
 use attr::AttrMetaMethods;
 use codemap;
 use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute};
-use codemap::{CompilerExpansion, CompilerExpansionFormat};
 use ext::base::*;
 use feature_gate::{self, Features, GatedCfg};
 use fold;
 use fold::*;
 use parse;
 use parse::token::{fresh_mark, fresh_name, intern};
-use parse::token;
 use ptr::P;
 use util::small_vector::SmallVector;
 use visit;
 use visit::Visitor;
 use std_inject;
 
-// Given suffix ["b","c","d"], returns path `::std::b::c::d` when
-// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
-fn mk_core_path(fld: &mut MacroExpander,
-                span: Span,
-                suffix: &[&'static str]) -> ast::Path {
-    let idents = fld.cx.std_path(suffix);
-    fld.cx.path_global(span, idents)
-}
 
 pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
-    fn push_compiler_expansion(fld: &mut MacroExpander, span: Span,
-                               expansion_type: CompilerExpansionFormat) {
-        fld.cx.bt_push(ExpnInfo {
-            call_site: span,
-            callee: NameAndSpan {
-                format: CompilerExpansion(expansion_type),
-
-                // This does *not* mean code generated after
-                // `push_compiler_expansion` is automatically exempt
-                // from stability lints; must also tag such code with
-                // an appropriate span from `fld.cx.backtrace()`.
-                allow_internal_unstable: true,
-
-                span: None,
-            },
-        });
-    }
-
-    // Sets the expn_id so that we can use unstable methods.
-    fn allow_unstable(fld: &mut MacroExpander, span: Span) -> Span {
-        Span { expn_id: fld.cx.backtrace(), ..span }
-    }
-
     let expr_span = e.span;
     return e.and_then(|ast::Expr {id, node, span}| match node {
 
@@ -94,265 +61,39 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
             })
         }
 
-        // Desugar ExprBox: `in (PLACE) EXPR`
-        ast::ExprBox(Some(placer), value_expr) => {
-            // to:
-            //
-            // let p = PLACE;
-            // let mut place = Placer::make_place(p);
-            // let raw_place = Place::pointer(&mut place);
-            // push_unsafe!({
-            //     std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
-            //     InPlace::finalize(place)
-            // })
-
+        ast::ExprInPlace(placer, value_expr) => {
             // Ensure feature-gate is enabled
             feature_gate::check_for_placement_in(
                 fld.cx.ecfg.features,
                 &fld.cx.parse_sess.span_diagnostic,
                 expr_span);
 
-            push_compiler_expansion(fld, expr_span, CompilerExpansionFormat::PlacementIn);
-
-            let value_span = value_expr.span;
-            let placer_span = placer.span;
-
-            let placer_expr = fld.fold_expr(placer);
+            let placer = fld.fold_expr(placer);
             let value_expr = fld.fold_expr(value_expr);
-
-            let placer_ident = token::gensym_ident("placer");
-            let agent_ident = token::gensym_ident("place");
-            let p_ptr_ident = token::gensym_ident("p_ptr");
-
-            let placer = fld.cx.expr_ident(span, placer_ident);
-            let agent = fld.cx.expr_ident(span, agent_ident);
-            let p_ptr = fld.cx.expr_ident(span, p_ptr_ident);
-
-            let make_place = ["ops", "Placer", "make_place"];
-            let place_pointer = ["ops", "Place", "pointer"];
-            let move_val_init = ["intrinsics", "move_val_init"];
-            let inplace_finalize = ["ops", "InPlace", "finalize"];
-
-            let make_call = |fld: &mut MacroExpander, p, args| {
-                // We feed in the `expr_span` because codemap's span_allows_unstable
-                // allows the call_site span to inherit the `allow_internal_unstable`
-                // setting.
-                let span_unstable = allow_unstable(fld, expr_span);
-                let path = mk_core_path(fld, span_unstable, p);
-                let path = fld.cx.expr_path(path);
-                let expr_span_unstable = allow_unstable(fld, span);
-                fld.cx.expr_call(expr_span_unstable, path, args)
-            };
-
-            let stmt_let = |fld: &mut MacroExpander, bind, expr| {
-                fld.cx.stmt_let(placer_span, false, bind, expr)
-            };
-            let stmt_let_mut = |fld: &mut MacroExpander, bind, expr| {
-                fld.cx.stmt_let(placer_span, true, bind, expr)
-            };
-
-            // let placer = <placer_expr> ;
-            let s1 = stmt_let(fld, placer_ident, placer_expr);
-
-            // let mut place = Placer::make_place(placer);
-            let s2 = {
-                let call = make_call(fld, &make_place, vec![placer]);
-                stmt_let_mut(fld, agent_ident, call)
-            };
-
-            // let p_ptr = Place::pointer(&mut place);
-            let s3 = {
-                let args = vec![fld.cx.expr_mut_addr_of(placer_span, agent.clone())];
-                let call = make_call(fld, &place_pointer, args);
-                stmt_let(fld, p_ptr_ident, call)
-            };
-
-            // pop_unsafe!(EXPR));
-            let pop_unsafe_expr = pop_unsafe_expr(fld.cx, value_expr, value_span);
-
-            // push_unsafe!({
-            //     ptr::write(p_ptr, pop_unsafe!(<value_expr>));
-            //     InPlace::finalize(place)
-            // })
-            let expr = {
-                let call_move_val_init = StmtSemi(make_call(
-                    fld, &move_val_init, vec![p_ptr, pop_unsafe_expr]), ast::DUMMY_NODE_ID);
-                let call_move_val_init = codemap::respan(value_span, call_move_val_init);
-
-                let call = make_call(fld, &inplace_finalize, vec![agent]);
-                Some(push_unsafe_expr(fld.cx, vec![P(call_move_val_init)], call, span))
-            };
-
-            let block = fld.cx.block_all(span, vec![s1, s2, s3], expr);
-            let result = fld.cx.expr_block(block);
-            fld.cx.bt_pop();
-            result
+            fld.cx.expr(span, ast::ExprInPlace(placer, value_expr))
         }
 
-        // Issue #22181:
-        // Eventually a desugaring for `box EXPR`
-        // (similar to the desugaring above for `in PLACE BLOCK`)
-        // should go here, desugaring
-        //
-        // to:
-        //
-        // let mut place = BoxPlace::make_place();
-        // let raw_place = Place::pointer(&mut place);
-        // let value = $value;
-        // unsafe {
-        //     ::std::ptr::write(raw_place, value);
-        //     Boxed::finalize(place)
-        // }
-        //
-        // But for now there are type-inference issues doing that.
-
         ast::ExprWhile(cond, body, opt_ident) => {
             let cond = fld.fold_expr(cond);
             let (body, opt_ident) = expand_loop_block(body, opt_ident, fld);
             fld.cx.expr(span, ast::ExprWhile(cond, body, opt_ident))
         }
 
-        // Desugar ExprWhileLet
-        // From: `[opt_ident]: while let <pat> = <expr> <body>`
         ast::ExprWhileLet(pat, expr, body, opt_ident) => {
-            // to:
-            //
-            //   [opt_ident]: loop {
-            //     match <expr> {
-            //       <pat> => <body>,
-            //       _ => break
-            //     }
-            //   }
-
-            push_compiler_expansion(fld, span, CompilerExpansionFormat::WhileLet);
-
-            // `<pat> => <body>`
-            let pat_arm = {
-                let body_expr = fld.cx.expr_block(body);
-                fld.cx.arm(pat.span, vec![pat], body_expr)
-            };
-
-            // `_ => break`
-            let break_arm = {
-                let pat_under = fld.cx.pat_wild(span);
-                let break_expr = fld.cx.expr_break(span);
-                fld.cx.arm(span, vec![pat_under], break_expr)
-            };
-
-            // `match <expr> { ... }`
-            let arms = vec![pat_arm, break_arm];
-            let match_expr = fld.cx.expr(span,
-                                    ast::ExprMatch(expr, arms, ast::MatchSource::WhileLetDesugar));
-
-            // `[opt_ident]: loop { ... }`
-            let loop_block = fld.cx.block_expr(match_expr);
-            let (loop_block, opt_ident) = expand_loop_block(loop_block, opt_ident, fld);
-            let result = fld.cx.expr(span, ast::ExprLoop(loop_block, opt_ident));
-            fld.cx.bt_pop();
-            result
-        }
-
-        // Desugar ExprIfLet
-        // From: `if let <pat> = <expr> <body> [<elseopt>]`
-        ast::ExprIfLet(pat, expr, body, mut elseopt) => {
-            // to:
-            //
-            //   match <expr> {
-            //     <pat> => <body>,
-            //     [_ if <elseopt_if_cond> => <elseopt_if_body>,]
-            //     _ => [<elseopt> | ()]
-            //   }
-
-            push_compiler_expansion(fld, span, CompilerExpansionFormat::IfLet);
-
-            // `<pat> => <body>`
-            let pat_arm = {
-                let body_expr = fld.cx.expr_block(body);
-                fld.cx.arm(pat.span, vec![pat], body_expr)
-            };
-
-            // `[_ if <elseopt_if_cond> => <elseopt_if_body>,]`
-            let else_if_arms = {
-                let mut arms = vec![];
-                loop {
-                    let elseopt_continue = elseopt
-                        .and_then(|els| els.and_then(|els| match els.node {
-                        // else if
-                        ast::ExprIf(cond, then, elseopt) => {
-                            let pat_under = fld.cx.pat_wild(span);
-                            arms.push(ast::Arm {
-                                attrs: vec![],
-                                pats: vec![pat_under],
-                                guard: Some(cond),
-                                body: fld.cx.expr_block(then)
-                            });
-                            elseopt.map(|elseopt| (elseopt, true))
-                        }
-                        _ => Some((P(els), false))
-                    }));
-                    match elseopt_continue {
-                        Some((e, true)) => {
-                            elseopt = Some(e);
-                        }
-                        Some((e, false)) => {
-                            elseopt = Some(e);
-                            break;
-                        }
-                        None => {
-                            elseopt = None;
-                            break;
-                        }
-                    }
-                }
-                arms
-            };
-
-            let contains_else_clause = elseopt.is_some();
-
-            // `_ => [<elseopt> | ()]`
-            let else_arm = {
-                let pat_under = fld.cx.pat_wild(span);
-                let else_expr = elseopt.unwrap_or_else(|| fld.cx.expr_tuple(span, vec![]));
-                fld.cx.arm(span, vec![pat_under], else_expr)
-            };
-
-            let mut arms = Vec::with_capacity(else_if_arms.len() + 2);
-            arms.push(pat_arm);
-            arms.extend(else_if_arms);
-            arms.push(else_arm);
-
-            let match_expr = fld.cx.expr(span,
-                                         ast::ExprMatch(expr, arms,
-                                                ast::MatchSource::IfLetDesugar {
-                                                    contains_else_clause: contains_else_clause,
-                                                }));
-            let result = fld.fold_expr(match_expr);
-            fld.cx.bt_pop();
-            result
-        }
+            let pat = fld.fold_pat(pat);
+            let expr = fld.fold_expr(expr);
+
+            // Hygienic renaming of the body.
+            let ((body, opt_ident), mut rewritten_pats) =
+                rename_in_scope(vec![pat],
+                                fld,
+                                (body, opt_ident),
+                                |rename_fld, fld, (body, opt_ident)| {
+                expand_loop_block(rename_fld.fold_block(body), opt_ident, fld)
+            });
+            assert!(rewritten_pats.len() == 1);
 
-        // Desugar support for ExprIfLet in the ExprIf else position
-        ast::ExprIf(cond, blk, elseopt) => {
-            let elseopt = elseopt.map(|els| els.and_then(|els| match els.node {
-                ast::ExprIfLet(..) => {
-                    push_compiler_expansion(fld, span, CompilerExpansionFormat::IfLet);
-                    // wrap the if-let expr in a block
-                    let span = els.span;
-                    let blk = P(ast::Block {
-                        stmts: vec![],
-                        expr: Some(P(els)),
-                        id: ast::DUMMY_NODE_ID,
-                        rules: ast::DefaultBlock,
-                        span: span
-                    });
-                    let result = fld.cx.expr_block(blk);
-                    fld.cx.bt_pop();
-                    result
-                }
-                _ => P(els)
-            }));
-            let if_expr = fld.cx.expr(span, ast::ExprIf(cond, blk, elseopt));
-            if_expr.map(|e| noop_fold_expr(e, fld))
+            fld.cx.expr(span, ast::ExprWhileLet(rewritten_pats.remove(0), expr, body, opt_ident))
         }
 
         ast::ExprLoop(loop_block, opt_ident) => {
@@ -360,102 +101,39 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
             fld.cx.expr(span, ast::ExprLoop(loop_block, opt_ident))
         }
 
-        // Desugar ExprForLoop
-        // From: `[opt_ident]: for <pat> in <head> <body>`
         ast::ExprForLoop(pat, head, body, opt_ident) => {
-            // to:
-            //
-            //   {
-            //     let result = match ::std::iter::IntoIterator::into_iter(<head>) {
-            //       mut iter => {
-            //         [opt_ident]: loop {
-            //           match ::std::iter::Iterator::next(&mut iter) {
-            //             ::std::option::Option::Some(<pat>) => <body>,
-            //             ::std::option::Option::None => break
-            //           }
-            //         }
-            //       }
-            //     };
-            //     result
-            //   }
-
-            push_compiler_expansion(fld, span, CompilerExpansionFormat::ForLoop);
-
-            let span = fld.new_span(span);
+            let pat = fld.fold_pat(pat);
+
+            // Hygienic renaming of the for loop body (for loop binds its pattern).
+            let ((body, opt_ident), mut rewritten_pats) =
+                rename_in_scope(vec![pat],
+                                fld,
+                                (body, opt_ident),
+                                |rename_fld, fld, (body, opt_ident)| {
+                expand_loop_block(rename_fld.fold_block(body), opt_ident, fld)
+            });
+            assert!(rewritten_pats.len() == 1);
 
-            // expand <head>
             let head = fld.fold_expr(head);
+            fld.cx.expr(span, ast::ExprForLoop(rewritten_pats.remove(0), head, body, opt_ident))
+        }
 
-            let iter = token::gensym_ident("iter");
-
-            let pat_span = fld.new_span(pat.span);
-            // `::std::option::Option::Some(<pat>) => <body>`
-            let pat_arm = {
-                let body_expr = fld.cx.expr_block(body);
-                let pat = fld.fold_pat(pat);
-                let some_pat = fld.cx.pat_some(pat_span, pat);
-
-                fld.cx.arm(pat_span, vec![some_pat], body_expr)
-            };
-
-            // `::std::option::Option::None => break`
-            let break_arm = {
-                let break_expr = fld.cx.expr_break(span);
-
-                fld.cx.arm(span, vec![fld.cx.pat_none(span)], break_expr)
-            };
-
-            // `match ::std::iter::Iterator::next(&mut iter) { ... }`
-            let match_expr = {
-                let next_path = {
-                    let strs = fld.cx.std_path(&["iter", "Iterator", "next"]);
-
-                    fld.cx.path_global(span, strs)
-                };
-                let ref_mut_iter = fld.cx.expr_mut_addr_of(span, fld.cx.expr_ident(span, iter));
-                let next_expr =
-                    fld.cx.expr_call(span, fld.cx.expr_path(next_path), vec![ref_mut_iter]);
-                let arms = vec![pat_arm, break_arm];
-
-                fld.cx.expr(pat_span,
-                            ast::ExprMatch(next_expr, arms, ast::MatchSource::ForLoopDesugar))
-            };
-
-            // `[opt_ident]: loop { ... }`
-            let loop_block = fld.cx.block_expr(match_expr);
-            let (loop_block, opt_ident) = expand_loop_block(loop_block, opt_ident, fld);
-            let loop_expr = fld.cx.expr(span, ast::ExprLoop(loop_block, opt_ident));
-
-            // `mut iter => { ... }`
-            let iter_arm = {
-                let iter_pat =
-                    fld.cx.pat_ident_binding_mode(span, iter, ast::BindByValue(ast::MutMutable));
-                fld.cx.arm(span, vec![iter_pat], loop_expr)
-            };
-
-            // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
-            let into_iter_expr = {
-                let into_iter_path = {
-                    let strs = fld.cx.std_path(&["iter", "IntoIterator",
-                                                 "into_iter"]);
-
-                    fld.cx.path_global(span, strs)
-                };
+        ast::ExprIfLet(pat, sub_expr, body, else_opt) => {
+            let pat = fld.fold_pat(pat);
 
-                fld.cx.expr_call(span, fld.cx.expr_path(into_iter_path), vec![head])
-            };
-
-            let match_expr = fld.cx.expr_match(span, into_iter_expr, vec![iter_arm]);
+            // Hygienic renaming of the body.
+            let (body, mut rewritten_pats) =
+                rename_in_scope(vec![pat],
+                                fld,
+                                body,
+                                |rename_fld, fld, body| {
+                fld.fold_block(rename_fld.fold_block(body))
+            });
+            assert!(rewritten_pats.len() == 1);
 
-            // `{ let result = ...; result }`
-            let result_ident = token::gensym_ident("result");
-            let result = fld.cx.expr_block(
-                fld.cx.block_all(
-                    span,
-                    vec![fld.cx.stmt_let(span, false, result_ident, match_expr)],
-                    Some(fld.cx.expr_ident(span, result_ident))));
-            fld.cx.bt_pop();
-            result
+            let else_opt = else_opt.map(|else_opt| fld.fold_expr(else_opt));
+            let sub_expr = fld.fold_expr(sub_expr);
+            fld.cx.expr(span, ast::ExprIfLet(rewritten_pats.remove(0), sub_expr, body, else_opt))
         }
 
         ast::ExprClosure(capture_clause, fn_decl, block) => {
@@ -475,25 +153,6 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
             }, fld))
         }
     });
-
-    fn push_unsafe_expr(cx: &mut ExtCtxt, stmts: Vec<P<ast::Stmt>>,
-                        expr: P<ast::Expr>, span: Span)
-                        -> P<ast::Expr> {
-        let rules = ast::PushUnsafeBlock(ast::CompilerGenerated);
-        cx.expr_block(P(ast::Block {
-            rules: rules, span: span, id: ast::DUMMY_NODE_ID,
-            stmts: stmts, expr: Some(expr),
-        }))
-    }
-
-    fn pop_unsafe_expr(cx: &mut ExtCtxt, expr: P<ast::Expr>, span: Span)
-                       -> P<ast::Expr> {
-        let rules = ast::PopUnsafeBlock(ast::CompilerGenerated);
-        cx.expr_block(P(ast::Block {
-            rules: rules, span: span, id: ast::DUMMY_NODE_ID,
-            stmts: vec![], expr: Some(expr),
-        }))
-    }
 }
 
 /// Expand a (not-ident-style) macro invocation. Returns the result
@@ -509,78 +168,75 @@ fn expand_mac_invoc<T, F, G>(mac: ast::Mac,
     F: for<'a> FnOnce(Box<MacResult+'a>) -> Option<T>,
     G: FnOnce(T, Mrk) -> T,
 {
-    match mac.node {
-        // it would almost certainly be cleaner to pass the whole
-        // macro invocation in, rather than pulling it apart and
-        // marking the tts and the ctxt separately. This also goes
-        // for the other three macro invocation chunks of code
-        // in this file.
-        // Token-tree macros:
-        MacInvocTT(pth, tts, _) => {
-            if pth.segments.len() > 1 {
-                fld.cx.span_err(pth.span,
-                                "expected macro name without module \
-                                separators");
-                // let compilation continue
-                return None;
-            }
-            let extname = pth.segments[0].identifier.name;
-            match fld.cx.syntax_env.find(&extname) {
-                None => {
-                    fld.cx.span_err(
-                        pth.span,
-                        &format!("macro undefined: '{}!'",
-                                &extname));
+    // it would almost certainly be cleaner to pass the whole
+    // macro invocation in, rather than pulling it apart and
+    // marking the tts and the ctxt separately. This also goes
+    // for the other three macro invocation chunks of code
+    // in this file.
+
+    let Mac_ { path: pth, tts, .. } = mac.node;
+    if pth.segments.len() > 1 {
+        fld.cx.span_err(pth.span,
+                        "expected macro name without module \
+                        separators");
+        // let compilation continue
+        return None;
+    }
+    let extname = pth.segments[0].identifier.name;
+    match fld.cx.syntax_env.find(extname) {
+        None => {
+            fld.cx.span_err(
+                pth.span,
+                &format!("macro undefined: '{}!'",
+                        &extname));
 
-                    // let compilation continue
-                    None
-                }
-                Some(rc) => match *rc {
-                    NormalTT(ref expandfun, exp_span, allow_internal_unstable) => {
-                        fld.cx.bt_push(ExpnInfo {
-                                call_site: span,
-                                callee: NameAndSpan {
-                                    format: MacroBang(extname),
-                                    span: exp_span,
-                                    allow_internal_unstable: allow_internal_unstable,
-                                },
-                            });
-                        let fm = fresh_mark();
-                        let marked_before = mark_tts(&tts[..], fm);
-
-                        // The span that we pass to the expanders we want to
-                        // be the root of the call stack. That's the most
-                        // relevant span and it's the actual invocation of
-                        // the macro.
-                        let mac_span = fld.cx.original_span();
-
-                        let opt_parsed = {
-                            let expanded = expandfun.expand(fld.cx,
-                                                            mac_span,
-                                                            &marked_before[..]);
-                            parse_thunk(expanded)
-                        };
-                        let parsed = match opt_parsed {
-                            Some(e) => e,
-                            None => {
-                                fld.cx.span_err(
-                                    pth.span,
-                                    &format!("non-expression macro in expression position: {}",
-                                            extname
-                                            ));
-                                return None;
-                            }
-                        };
-                        Some(mark_thunk(parsed,fm))
-                    }
-                    _ => {
+            // let compilation continue
+            None
+        }
+        Some(rc) => match *rc {
+            NormalTT(ref expandfun, exp_span, allow_internal_unstable) => {
+                fld.cx.bt_push(ExpnInfo {
+                        call_site: span,
+                        callee: NameAndSpan {
+                            format: MacroBang(extname),
+                            span: exp_span,
+                            allow_internal_unstable: allow_internal_unstable,
+                        },
+                    });
+                let fm = fresh_mark();
+                let marked_before = mark_tts(&tts[..], fm);
+
+                // The span that we pass to the expanders we want to
+                // be the root of the call stack. That's the most
+                // relevant span and it's the actual invocation of
+                // the macro.
+                let mac_span = fld.cx.original_span();
+
+                let opt_parsed = {
+                    let expanded = expandfun.expand(fld.cx,
+                                                    mac_span,
+                                                    &marked_before[..]);
+                    parse_thunk(expanded)
+                };
+                let parsed = match opt_parsed {
+                    Some(e) => e,
+                    None => {
                         fld.cx.span_err(
                             pth.span,
-                            &format!("'{}' is not a tt-style macro",
-                                    extname));
-                        None
+                            &format!("non-expression macro in expression position: {}",
+                                    extname
+                                    ));
+                        return None;
                     }
-                }
+                };
+                Some(mark_thunk(parsed,fm))
+            }
+            _ => {
+                fld.cx.span_err(
+                    pth.span,
+                    &format!("'{}' is not a tt-style macro",
+                            extname));
+                None
             }
         }
     }
@@ -596,7 +252,7 @@ fn expand_loop_block(loop_block: P<Block>,
                      fld: &mut MacroExpander) -> (P<Block>, Option<Ident>) {
     match opt_ident {
         Some(label) => {
-            let new_label = fresh_name(&label);
+            let new_label = fresh_name(label);
             let rename = (label, new_label);
 
             // The rename *must not* be added to the pending list of current
@@ -663,7 +319,7 @@ fn contains_macro_use(fld: &mut MacroExpander, attrs: &[ast::Attribute]) -> bool
         if attr.check_name("macro_escape") {
             fld.cx.span_warn(attr.span, "macro_escape is a deprecated synonym for macro_use");
             is_use = true;
-            if let ast::AttrInner = attr.node.style {
+            if let ast::AttrStyle::Inner = attr.node.style {
                 fld.cx.fileline_help(attr.span, "consider an outer attribute, \
                                              #[macro_use] mod ...");
             }
@@ -684,19 +340,15 @@ fn contains_macro_use(fld: &mut MacroExpander, attrs: &[ast::Attribute]) -> bool
 // logic as for expression-position macro invocations.
 pub fn expand_item_mac(it: P<ast::Item>,
                        fld: &mut MacroExpander) -> SmallVector<P<ast::Item>> {
-    let (extname, path_span, tts) = match it.node {
-        ItemMac(codemap::Spanned {
-            node: MacInvocTT(ref pth, ref tts, _),
-            ..
-        }) => {
-            (pth.segments[0].identifier.name, pth.span, (*tts).clone())
-        }
+    let (extname, path_span, tts, span, attrs, ident) = it.and_then(|it| match it.node {
+        ItemMac(codemap::Spanned { node: Mac_ { path, tts, .. }, .. }) =>
+            (path.segments[0].identifier.name, path.span, tts, it.span, it.attrs, it.ident),
         _ => fld.cx.span_bug(it.span, "invalid item macro invocation")
-    };
+    });
 
     let fm = fresh_mark();
     let items = {
-        let expanded = match fld.cx.syntax_env.find(&extname) {
+        let expanded = match fld.cx.syntax_env.find(extname) {
             None => {
                 fld.cx.span_err(path_span,
                                 &format!("macro undefined: '{}!'",
@@ -706,48 +358,48 @@ pub fn expand_item_mac(it: P<ast::Item>,
             }
 
             Some(rc) => match *rc {
-                NormalTT(ref expander, span, allow_internal_unstable) => {
-                    if it.ident.name != parse::token::special_idents::invalid.name {
+                NormalTT(ref expander, tt_span, allow_internal_unstable) => {
+                    if ident.name != parse::token::special_idents::invalid.name {
                         fld.cx
                             .span_err(path_span,
                                       &format!("macro {}! expects no ident argument, given '{}'",
                                                extname,
-                                               it.ident));
+                                               ident));
                         return SmallVector::zero();
                     }
                     fld.cx.bt_push(ExpnInfo {
-                        call_site: it.span,
+                        call_site: span,
                         callee: NameAndSpan {
                             format: MacroBang(extname),
-                            span: span,
+                            span: tt_span,
                             allow_internal_unstable: allow_internal_unstable,
                         }
                     });
                     // mark before expansion:
                     let marked_before = mark_tts(&tts[..], fm);
-                    expander.expand(fld.cx, it.span, &marked_before[..])
+                    expander.expand(fld.cx, span, &marked_before[..])
                 }
-                IdentTT(ref expander, span, allow_internal_unstable) => {
-                    if it.ident.name == parse::token::special_idents::invalid.name {
+                IdentTT(ref expander, tt_span, allow_internal_unstable) => {
+                    if ident.name == parse::token::special_idents::invalid.name {
                         fld.cx.span_err(path_span,
                                         &format!("macro {}! expects an ident argument",
                                                 extname));
                         return SmallVector::zero();
                     }
                     fld.cx.bt_push(ExpnInfo {
-                        call_site: it.span,
+                        call_site: span,
                         callee: NameAndSpan {
                             format: MacroBang(extname),
-                            span: span,
+                            span: tt_span,
                             allow_internal_unstable: allow_internal_unstable,
                         }
                     });
                     // mark before expansion:
                     let marked_tts = mark_tts(&tts[..], fm);
-                    expander.expand(fld.cx, it.span, it.ident, marked_tts)
+                    expander.expand(fld.cx, span, ident, marked_tts)
                 }
                 MacroRulesTT => {
-                    if it.ident.name == parse::token::special_idents::invalid.name {
+                    if ident.name == parse::token::special_idents::invalid.name {
                         fld.cx.span_err(path_span,
                                         &format!("macro_rules! expects an ident argument")
                                         );
@@ -755,7 +407,7 @@ pub fn expand_item_mac(it: P<ast::Item>,
                     }
 
                     fld.cx.bt_push(ExpnInfo {
-                        call_site: it.span,
+                        call_site: span,
                         callee: NameAndSpan {
                             format: MacroBang(extname),
                             span: None,
@@ -767,7 +419,7 @@ pub fn expand_item_mac(it: P<ast::Item>,
                     });
                     // DON'T mark before expansion.
 
-                    let allow_internal_unstable = attr::contains_name(&it.attrs,
+                    let allow_internal_unstable = attr::contains_name(&attrs,
                                                                       "allow_internal_unstable");
 
                     // ensure any #[allow_internal_unstable]s are
@@ -777,18 +429,19 @@ pub fn expand_item_mac(it: P<ast::Item>,
                         feature_gate::emit_feature_err(
                             &fld.cx.parse_sess.span_diagnostic,
                             "allow_internal_unstable",
-                            it.span,
+                            span,
                             feature_gate::GateIssue::Language,
                             feature_gate::EXPLAIN_ALLOW_INTERNAL_UNSTABLE)
                     }
 
+                    let export = attr::contains_name(&attrs, "macro_export");
                     let def = ast::MacroDef {
-                        ident: it.ident,
-                        attrs: it.attrs.clone(),
+                        ident: ident,
+                        attrs: attrs,
                         id: ast::DUMMY_NODE_ID,
-                        span: it.span,
+                        span: span,
                         imported_from: None,
-                        export: attr::contains_name(&it.attrs, "macro_export"),
+                        export: export,
                         use_locally: true,
                         allow_internal_unstable: allow_internal_unstable,
                         body: tts,
@@ -800,7 +453,7 @@ pub fn expand_item_mac(it: P<ast::Item>,
                     return SmallVector::zero();
                 }
                 _ => {
-                    fld.cx.span_err(it.span,
+                    fld.cx.span_err(span,
                                     &format!("{}! is not legal in item position",
                                             extname));
                     return SmallVector::zero();
@@ -898,7 +551,7 @@ fn expand_non_macro_stmt(Spanned {node, span: stmt_span}: Stmt, fld: &mut MacroE
                     // generate fresh names, push them to a new pending list
                     let idents = pattern_bindings(&*expanded_pat);
                     let mut new_pending_renames =
-                        idents.iter().map(|ident| (*ident, fresh_name(ident))).collect();
+                        idents.iter().map(|ident| (*ident, fresh_name(*ident))).collect();
                     // rewrite the pattern using the new names (the old
                     // ones have already been applied):
                     let rewritten_pat = {
@@ -954,18 +607,18 @@ fn expand_arm(arm: ast::Arm, fld: &mut MacroExpander) -> ast::Arm {
     if expanded_pats.is_empty() {
         panic!("encountered match arm with 0 patterns");
     }
-    // all of the pats must have the same set of bindings, so use the
-    // first one to extract them and generate new names:
-    let idents = pattern_bindings(&*expanded_pats[0]);
-    let new_renames = idents.into_iter().map(|id| (id, fresh_name(&id))).collect();
-    // apply the renaming, but only to the PatIdents:
-    let mut rename_pats_fld = PatIdentRenamer{renames:&new_renames};
-    let rewritten_pats = expanded_pats.move_map(|pat| rename_pats_fld.fold_pat(pat));
+
     // apply renaming and then expansion to the guard and the body:
-    let mut rename_fld = IdentRenamer{renames:&new_renames};
-    let rewritten_guard =
-        arm.guard.map(|g| fld.fold_expr(rename_fld.fold_expr(g)));
-    let rewritten_body = fld.fold_expr(rename_fld.fold_expr(arm.body));
+    let ((rewritten_guard, rewritten_body), rewritten_pats) =
+        rename_in_scope(expanded_pats,
+                        fld,
+                        (arm.guard, arm.body),
+                        |rename_fld, fld, (ag, ab)|{
+        let rewritten_guard = ag.map(|g| fld.fold_expr(rename_fld.fold_expr(g)));
+        let rewritten_body = fld.fold_expr(rename_fld.fold_expr(ab));
+        (rewritten_guard, rewritten_body)
+    });
+
     ast::Arm {
         attrs: fold::fold_attrs(arm.attrs, fld),
         pats: rewritten_pats,
@@ -974,6 +627,25 @@ fn expand_arm(arm: ast::Arm, fld: &mut MacroExpander) -> ast::Arm {
     }
 }
 
+fn rename_in_scope<X, F>(pats: Vec<P<ast::Pat>>,
+                         fld: &mut MacroExpander,
+                         x: X,
+                         f: F)
+                         -> (X, Vec<P<ast::Pat>>)
+    where F: Fn(&mut IdentRenamer, &mut MacroExpander, X) -> X
+{
+    // all of the pats must have the same set of bindings, so use the
+    // first one to extract them and generate new names:
+    let idents = pattern_bindings(&*pats[0]);
+    let new_renames = idents.into_iter().map(|id| (id, fresh_name(id))).collect();
+    // apply the renaming, but only to the PatIdents:
+    let mut rename_pats_fld = PatIdentRenamer{renames:&new_renames};
+    let rewritten_pats = pats.move_map(|pat| rename_pats_fld.fold_pat(pat));
+
+    let mut rename_fld = IdentRenamer{ renames:&new_renames };
+    (f(&mut rename_fld, fld, x), rewritten_pats)
+}
+
 /// A visitor that extracts the PatIdent (binding) paths
 /// from a given thingy and puts them in a mutable
 /// array
@@ -1059,11 +731,7 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> {
     }
     p.map(|ast::Pat {node, span, ..}| {
         let (pth, tts) = match node {
-            PatMac(mac) => match mac.node {
-                MacInvocTT(pth, tts, _) => {
-                    (pth, tts)
-                }
-            },
+            PatMac(mac) => (mac.node.path, mac.node.tts),
             _ => unreachable!()
         };
         if pth.segments.len() > 1 {
@@ -1071,7 +739,7 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> {
             return DummyResult::raw_pat(span);
         }
         let extname = pth.segments[0].identifier.name;
-        let marked_after = match fld.cx.syntax_env.find(&extname) {
+        let marked_after = match fld.cx.syntax_env.find(extname) {
             None => {
                 fld.cx.span_err(pth.span,
                                 &format!("macro undefined: '{}!'",
@@ -1144,10 +812,7 @@ pub struct IdentRenamer<'a> {
 
 impl<'a> Folder for IdentRenamer<'a> {
     fn fold_ident(&mut self, id: Ident) -> Ident {
-        Ident {
-            name: id.name,
-            ctxt: mtwt::apply_renames(self.renames, id.ctxt),
-        }
+        Ident::new(id.name, mtwt::apply_renames(self.renames, id.ctxt))
     }
     fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
         fold::noop_fold_mac(mac, self)
@@ -1171,8 +836,8 @@ impl<'a> Folder for PatIdentRenamer<'a> {
 
         pat.map(|ast::Pat {id, node, span}| match node {
             ast::PatIdent(binding_mode, Spanned{span: sp, node: ident}, sub) => {
-                let new_ident = Ident{name: ident.name,
-                                      ctxt: mtwt::apply_renames(self.renames, ident.ctxt)};
+                let new_ident = Ident::new(ident.name,
+                                           mtwt::apply_renames(self.renames, ident.ctxt));
                 let new_node =
                     ast::PatIdent(binding_mode,
                                   Spanned{span: self.new_span(sp), node: new_ident},
@@ -1264,7 +929,7 @@ macro_rules! partition {
                     fld: &MacroExpander)
                      -> (Vec<ast::Attribute>, Vec<ast::Attribute>) {
             attrs.iter().cloned().partition(|attr| {
-                match fld.cx.syntax_env.find(&intern(&attr.name())) {
+                match fld.cx.syntax_env.find(intern(&attr.name())) {
                     Some(rc) => match *rc {
                         $variant(..) => true,
                         _ => false
@@ -1286,7 +951,7 @@ fn expand_decorators(a: Annotatable,
 {
     for attr in a.attrs() {
         let mname = intern(&attr.name());
-        match fld.cx.syntax_env.find(&mname) {
+        match fld.cx.syntax_env.find(mname) {
             Some(rc) => match *rc {
                 MultiDecorator(ref dec) => {
                     attr::mark_used(&attr);
@@ -1337,7 +1002,7 @@ fn expand_item_multi_modifier(mut it: Annotatable,
     for attr in &modifiers {
         let mname = intern(&attr.name());
 
-        match fld.cx.syntax_env.find(&mname) {
+        match fld.cx.syntax_env.find(mname) {
             Some(rc) => match *rc {
                 MultiModifier(ref mac) => {
                     attr::mark_used(attr);
@@ -1417,7 +1082,7 @@ fn expand_and_rename_fn_decl_and_block(fn_decl: P<ast::FnDecl>, block: P<ast::Bl
     let expanded_decl = fld.fold_fn_decl(fn_decl);
     let idents = fn_decl_arg_bindings(&*expanded_decl);
     let renames =
-        idents.iter().map(|id : &ast::Ident| (*id,fresh_name(id))).collect();
+        idents.iter().map(|id| (*id,fresh_name(*id))).collect();
     // first, a renamer for the PatIdents, for the fn_decl:
     let mut rename_pat_fld = PatIdentRenamer{renames: &renames};
     let rewritten_fn_decl = rename_pat_fld.fold_fn_decl(expanded_decl);
@@ -1638,19 +1303,14 @@ struct Marker { mark: Mrk }
 
 impl Folder for Marker {
     fn fold_ident(&mut self, id: Ident) -> Ident {
-        ast::Ident {
-            name: id.name,
-            ctxt: mtwt::apply_mark(self.mark, id.ctxt)
-        }
+        ast::Ident::new(id.name, mtwt::apply_mark(self.mark, id.ctxt))
     }
     fn fold_mac(&mut self, Spanned {node, span}: ast::Mac) -> ast::Mac {
         Spanned {
-            node: match node {
-                MacInvocTT(path, tts, ctxt) => {
-                    MacInvocTT(self.fold_path(path),
-                               self.fold_tts(&tts[..]),
-                               mtwt::apply_mark(self.mark, ctxt))
-                }
+            node: Mac_ {
+                path: self.fold_path(node.path),
+                tts: self.fold_tts(&node.tts),
+                ctxt: mtwt::apply_mark(self.mark, node.ctxt),
             },
             span: span,
         }
@@ -2116,7 +1776,7 @@ foo_module!();
         // find the xx binding
         let bindings = crate_bindings(&cr);
         let cxbinds: Vec<&ast::Ident> =
-            bindings.iter().filter(|b| b.name == "xx").collect();
+            bindings.iter().filter(|b| b.name.as_str() == "xx").collect();
         let cxbinds: &[&ast::Ident] = &cxbinds[..];
         let cxbind = match (cxbinds.len(), cxbinds.get(0)) {
             (1, Some(b)) => *b,
@@ -2128,7 +1788,7 @@ foo_module!();
         // the xx binding should bind all of the xx varrefs:
         for (idx,v) in varrefs.iter().filter(|p| {
             p.segments.len() == 1
-            && p.segments[0].identifier.name == "xx"
+            && p.segments[0].identifier.name.as_str() == "xx"
         }).enumerate() {
             if mtwt::resolve(v.segments[0].identifier) != resolved_binding {
                 println!("uh oh, xx binding didn't match xx varref:");
index ce83b84efee805ac9d129d921a54b0e4296bbe3f..7ac0e8c64c27554844a2809c8bfe8fc58f458692 100644 (file)
@@ -35,7 +35,9 @@ use std::collections::HashMap;
 pub struct SCTable {
     table: RefCell<Vec<SyntaxContext_>>,
     mark_memo: RefCell<HashMap<(SyntaxContext,Mrk),SyntaxContext>>,
-    rename_memo: RefCell<HashMap<(SyntaxContext,Ident,Name),SyntaxContext>>,
+    // The pair (Name,SyntaxContext) is actually one Ident, but it needs to be hashed and
+    // compared as pair (name, ctxt) and not as an Ident
+    rename_memo: RefCell<HashMap<(SyntaxContext,(Name,SyntaxContext),Name),SyntaxContext>>,
 }
 
 #[derive(PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy, Clone)]
@@ -66,8 +68,9 @@ pub fn apply_mark(m: Mrk, ctxt: SyntaxContext) -> SyntaxContext {
 /// Extend a syntax context with a given mark and sctable (explicit memoization)
 fn apply_mark_internal(m: Mrk, ctxt: SyntaxContext, table: &SCTable) -> SyntaxContext {
     let key = (ctxt, m);
-    * table.mark_memo.borrow_mut().entry(key)
-        .or_insert_with(|| idx_push(&mut *table.table.borrow_mut(), Mark(m, ctxt)))
+    *table.mark_memo.borrow_mut().entry(key).or_insert_with(|| {
+        SyntaxContext(idx_push(&mut *table.table.borrow_mut(), Mark(m, ctxt)))
+    })
 }
 
 /// Extend a syntax context with a given rename
@@ -81,10 +84,11 @@ fn apply_rename_internal(id: Ident,
                        to: Name,
                        ctxt: SyntaxContext,
                        table: &SCTable) -> SyntaxContext {
-    let key = (ctxt, id, to);
+    let key = (ctxt, (id.name, id.ctxt), to);
 
-    * table.rename_memo.borrow_mut().entry(key)
-        .or_insert_with(|| idx_push(&mut *table.table.borrow_mut(), Rename(id, to, ctxt)))
+    *table.rename_memo.borrow_mut().entry(key).or_insert_with(|| {
+            SyntaxContext(idx_push(&mut *table.table.borrow_mut(), Rename(id, to, ctxt)))
+    })
 }
 
 /// Apply a list of renamings to a context
@@ -185,20 +189,20 @@ fn resolve_internal(id: Ident,
     }
 
     let resolved = {
-        let result = (*table.table.borrow())[id.ctxt as usize];
+        let result = (*table.table.borrow())[id.ctxt.0 as usize];
         match result {
             EmptyCtxt => id.name,
             // ignore marks here:
             Mark(_,subctxt) =>
-                resolve_internal(Ident{name:id.name, ctxt: subctxt},
+                resolve_internal(Ident::new(id.name, subctxt),
                                  table, resolve_table),
             // do the rename if necessary:
             Rename(Ident{name, ctxt}, toname, subctxt) => {
                 let resolvedfrom =
-                    resolve_internal(Ident{name:name, ctxt:ctxt},
+                    resolve_internal(Ident::new(name, ctxt),
                                      table, resolve_table);
                 let resolvedthis =
-                    resolve_internal(Ident{name:id.name, ctxt:subctxt},
+                    resolve_internal(Ident::new(id.name, subctxt),
                                      table, resolve_table);
                 if (resolvedthis == resolvedfrom)
                     && (marksof_internal(ctxt, resolvedthis, table)
@@ -229,7 +233,7 @@ fn marksof_internal(ctxt: SyntaxContext,
     let mut result = Vec::new();
     let mut loopvar = ctxt;
     loop {
-        let table_entry = (*table.table.borrow())[loopvar as usize];
+        let table_entry = (*table.table.borrow())[loopvar.0 as usize];
         match table_entry {
             EmptyCtxt => {
                 return result;
@@ -256,7 +260,7 @@ fn marksof_internal(ctxt: SyntaxContext,
 /// FAILS when outside is not a mark.
 pub fn outer_mark(ctxt: SyntaxContext) -> Mrk {
     with_sctable(|sctable| {
-        match (*sctable.table.borrow())[ctxt as usize] {
+        match (*sctable.table.borrow())[ctxt.0 as usize] {
             Mark(mrk, _) => mrk,
             _ => panic!("can't retrieve outer mark when outside is not a mark")
         }
@@ -302,7 +306,7 @@ mod tests {
     }
 
     fn id(n: u32, s: SyntaxContext) -> Ident {
-        Ident {name: Name(n), ctxt: s}
+        Ident::new(Name(n), s)
     }
 
     // because of the SCTable, I now need a tidy way of
@@ -328,7 +332,7 @@ mod tests {
         let mut result = Vec::new();
         loop {
             let table = table.table.borrow();
-            match (*table)[sc as usize] {
+            match (*table)[sc.0 as usize] {
                 EmptyCtxt => {return result;},
                 Mark(mrk,tail) => {
                     result.push(M(mrk));
@@ -349,15 +353,15 @@ mod tests {
     fn test_unfold_refold(){
         let mut t = new_sctable_internal();
 
-        let test_sc = vec!(M(3),R(id(101,0),Name(14)),M(9));
-        assert_eq!(unfold_test_sc(test_sc.clone(),EMPTY_CTXT,&mut t),4);
+        let test_sc = vec!(M(3),R(id(101,EMPTY_CTXT),Name(14)),M(9));
+        assert_eq!(unfold_test_sc(test_sc.clone(),EMPTY_CTXT,&mut t),SyntaxContext(4));
         {
             let table = t.table.borrow();
-            assert!((*table)[2] == Mark(9,0));
-            assert!((*table)[3] == Rename(id(101,0),Name(14),2));
-            assert!((*table)[4] == Mark(3,3));
+            assert!((*table)[2] == Mark(9,EMPTY_CTXT));
+            assert!((*table)[3] == Rename(id(101,EMPTY_CTXT),Name(14),SyntaxContext(2)));
+            assert!((*table)[4] == Mark(3,SyntaxContext(3)));
         }
-        assert_eq!(refold_test_sc(4,&t),test_sc);
+        assert_eq!(refold_test_sc(SyntaxContext(4),&t),test_sc);
     }
 
     // extend a syntax context with a sequence of marks given
@@ -371,11 +375,11 @@ mod tests {
     #[test] fn unfold_marks_test() {
         let mut t = new_sctable_internal();
 
-        assert_eq!(unfold_marks(vec!(3,7),EMPTY_CTXT,&mut t),3);
+        assert_eq!(unfold_marks(vec!(3,7),EMPTY_CTXT,&mut t),SyntaxContext(3));
         {
             let table = t.table.borrow();
-            assert!((*table)[2] == Mark(7,0));
-            assert!((*table)[3] == Mark(3,2));
+            assert!((*table)[2] == Mark(7,EMPTY_CTXT));
+            assert!((*table)[3] == Mark(3,SyntaxContext(2)));
         }
     }
 
@@ -396,7 +400,7 @@ mod tests {
          assert_eq! (marksof_internal (ans, stopname,&t), [16]);}
         // rename where stop doesn't match:
         { let chain = vec!(M(9),
-                        R(id(name1.usize() as u32,
+                        R(id(name1.0,
                              apply_mark_internal (4, EMPTY_CTXT,&mut t)),
                           Name(100101102)),
                         M(14));
@@ -405,7 +409,7 @@ mod tests {
         // rename where stop does match
         { let name1sc = apply_mark_internal(4, EMPTY_CTXT, &mut t);
          let chain = vec!(M(9),
-                       R(id(name1.usize() as u32, name1sc),
+                       R(id(name1.0, name1sc),
                          stopname),
                        M(14));
          let ans = unfold_test_sc(chain,EMPTY_CTXT,&mut t);
@@ -474,10 +478,10 @@ mod tests {
     #[test]
     fn hashing_tests () {
         let mut t = new_sctable_internal();
-        assert_eq!(apply_mark_internal(12,EMPTY_CTXT,&mut t),2);
-        assert_eq!(apply_mark_internal(13,EMPTY_CTXT,&mut t),3);
+        assert_eq!(apply_mark_internal(12,EMPTY_CTXT,&mut t),SyntaxContext(2));
+        assert_eq!(apply_mark_internal(13,EMPTY_CTXT,&mut t),SyntaxContext(3));
         // using the same one again should result in the same index:
-        assert_eq!(apply_mark_internal(12,EMPTY_CTXT,&mut t),2);
+        assert_eq!(apply_mark_internal(12,EMPTY_CTXT,&mut t),SyntaxContext(2));
         // I'm assuming that the rename table will behave the same....
     }
 
@@ -496,10 +500,10 @@ mod tests {
 
     #[test]
     fn new_resolves_test() {
-        let renames = vec!((Ident{name:Name(23),ctxt:EMPTY_CTXT},Name(24)),
-                           (Ident{name:Name(29),ctxt:EMPTY_CTXT},Name(29)));
+        let renames = vec!((Ident::with_empty_ctxt(Name(23)),Name(24)),
+                           (Ident::with_empty_ctxt(Name(29)),Name(29)));
         let new_ctxt1 = apply_renames(&renames,EMPTY_CTXT);
-        assert_eq!(resolve(Ident{name:Name(23),ctxt:new_ctxt1}),Name(24));
-        assert_eq!(resolve(Ident{name:Name(29),ctxt:new_ctxt1}),Name(29));
+        assert_eq!(resolve(Ident::new(Name(23),new_ctxt1)),Name(24));
+        assert_eq!(resolve(Ident::new(Name(29),new_ctxt1)),Name(29));
     }
 }
diff --git a/src/libsyntax/ext/pushpop_safe.rs b/src/libsyntax/ext/pushpop_safe.rs
deleted file mode 100644 (file)
index a67d550..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*
- * The compiler code necessary to support the `push_unsafe!` and
- * `pop_unsafe!` macros.
- *
- * This is a hack to allow a kind of "safety hygiene", where a macro
- * can generate code with an interior expression that inherits the
- * safety of some outer context.
- *
- * For example, in:
- *
- * ```rust
- * fn foo() { push_unsafe!( { EXPR_1; pop_unsafe!( EXPR_2 ) } ) }
- * ```
- *
- * the `EXPR_1` is considered to be in an `unsafe` context,
- * but `EXPR_2` is considered to be in a "safe" (i.e. checked) context.
- *
- * For comparison, in:
- *
- * ```rust
- * fn foo() { unsafe { push_unsafe!( { EXPR_1; pop_unsafe!( EXPR_2 ) } ) } }
- * ```
- *
- * both `EXPR_1` and `EXPR_2` are considered to be in `unsafe`
- * contexts.
- *
- */
-
-use ast;
-use codemap::Span;
-use ext::base::*;
-use ext::base;
-use ext::build::AstBuilder;
-use feature_gate;
-use ptr::P;
-
-enum PushPop { Push, Pop }
-
-pub fn expand_push_unsafe<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                               -> Box<base::MacResult+'cx> {
-    expand_pushpop_unsafe(cx, sp, tts, PushPop::Push)
-}
-
-pub fn expand_pop_unsafe<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-                               -> Box<base::MacResult+'cx> {
-    expand_pushpop_unsafe(cx, sp, tts, PushPop::Pop)
-}
-
-fn expand_pushpop_unsafe<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree],
-                                  pp: PushPop) -> Box<base::MacResult+'cx> {
-    feature_gate::check_for_pushpop_syntax(
-        cx.ecfg.features, &cx.parse_sess.span_diagnostic, sp);
-
-    let mut exprs = match get_exprs_from_tts(cx, sp, tts) {
-        Some(exprs) => exprs.into_iter(),
-        None => return DummyResult::expr(sp),
-    };
-
-    let expr = match (exprs.next(), exprs.next()) {
-        (Some(expr), None) => expr,
-        _ => {
-            let msg = match pp {
-                PushPop::Push => "push_unsafe! takes 1 arguments",
-                PushPop::Pop => "pop_unsafe! takes 1 arguments",
-            };
-            cx.span_err(sp, msg);
-            return DummyResult::expr(sp);
-        }
-    };
-
-    let source = ast::UnsafeSource::CompilerGenerated;
-    let check_mode = match pp {
-        PushPop::Push => ast::BlockCheckMode::PushUnsafeBlock(source),
-        PushPop::Pop => ast::BlockCheckMode::PopUnsafeBlock(source),
-    };
-
-    MacEager::expr(cx.expr_block(P(ast::Block {
-        stmts: vec![],
-        expr: Some(expr),
-        id: ast::DUMMY_NODE_ID,
-        rules: check_mode,
-        span: sp
-    })))
-}
index b8168297190562b611cc573559f11bcb511640d8..e5fd15559ecffede4af2eba5c085992858b1f3b6 100644 (file)
@@ -187,7 +187,7 @@ pub mod rt {
             let mut r = vec![];
             // FIXME: The spans could be better
             r.push(ast::TtToken(self.span, token::Pound));
-            if self.node.style == ast::AttrInner {
+            if self.node.style == ast::AttrStyle::Inner {
                 r.push(ast::TtToken(self.span, token::Not));
             }
             r.push(ast::TtDelimited(self.span, Rc::new(ast::Delimited {
@@ -464,7 +464,7 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
         ($name: expr, $suffix: expr, $($args: expr),*) => {{
             let inner = cx.expr_call(sp, mk_token_path(cx, sp, $name), vec![$($args),*]);
             let suffix = match $suffix {
-                Some(name) => cx.expr_some(sp, mk_name(cx, sp, ast::Ident::new(name))),
+                Some(name) => cx.expr_some(sp, mk_name(cx, sp, ast::Ident::with_empty_ctxt(name))),
                 None => cx.expr_none(sp)
             };
             cx.expr_call(sp, mk_token_path(cx, sp, "Literal"), vec![inner, suffix])
@@ -489,31 +489,32 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
         }
 
         token::Literal(token::Byte(i), suf) => {
-            let e_byte = mk_name(cx, sp, i.ident());
+            let e_byte = mk_name(cx, sp, ast::Ident::with_empty_ctxt(i));
             return mk_lit!("Byte", suf, e_byte);
         }
 
         token::Literal(token::Char(i), suf) => {
-            let e_char = mk_name(cx, sp, i.ident());
+            let e_char = mk_name(cx, sp, ast::Ident::with_empty_ctxt(i));
             return mk_lit!("Char", suf, e_char);
         }
 
         token::Literal(token::Integer(i), suf) => {
-            let e_int = mk_name(cx, sp, i.ident());
+            let e_int = mk_name(cx, sp, ast::Ident::with_empty_ctxt(i));
             return mk_lit!("Integer", suf, e_int);
         }
 
         token::Literal(token::Float(fident), suf) => {
-            let e_fident = mk_name(cx, sp, fident.ident());
+            let e_fident = mk_name(cx, sp, ast::Ident::with_empty_ctxt(fident));
             return mk_lit!("Float", suf, e_fident);
         }
 
         token::Literal(token::Str_(ident), suf) => {
-            return mk_lit!("Str_", suf, mk_name(cx, sp, ident.ident()))
+            return mk_lit!("Str_", suf, mk_name(cx, sp, ast::Ident::with_empty_ctxt(ident)))
         }
 
         token::Literal(token::StrRaw(ident, n), suf) => {
-            return mk_lit!("StrRaw", suf, mk_name(cx, sp, ident.ident()), cx.expr_usize(sp, n))
+            return mk_lit!("StrRaw", suf, mk_name(cx, sp, ast::Ident::with_empty_ctxt(ident)),
+                           cx.expr_usize(sp, n))
         }
 
         token::Ident(ident, style) => {
@@ -535,7 +536,7 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
         token::DocComment(ident) => {
             return cx.expr_call(sp,
                                 mk_token_path(cx, sp, "DocComment"),
-                                vec!(mk_name(cx, sp, ident.ident())));
+                                vec!(mk_name(cx, sp, ast::Ident::with_empty_ctxt(ident))));
         }
 
         token::MatchNt(name, kind, namep, kindp) => {
index f6513cc3e255297d279dae08d18274302c62fb09..8dec9ae1e98750b1e6d604278ba8596987db749e 100644 (file)
@@ -32,7 +32,7 @@
 //! As it processes them, it fills up `eof_eis` with items that would be valid if
 //! the macro invocation is now over, `bb_eis` with items that are waiting on
 //! a Rust nonterminal like `$e:expr`, and `next_eis` with items that are waiting
-//! on the a particular token. Most of the logic concerns moving the · through the
+//! on a particular token. Most of the logic concerns moving the · through the
 //! repetitions indicated by Kleene stars. It only advances or calls out to the
 //! real Rust parser when no `cur_eis` items remain
 //!
@@ -79,7 +79,7 @@ pub use self::ParseResult::*;
 use self::TokenTreeOrTokenTreeVec::*;
 
 use ast;
-use ast::{TokenTree, Ident};
+use ast::{TokenTree, Name};
 use ast::{TtDelimited, TtSequence, TtToken};
 use codemap::{BytePos, mk_sp, Span};
 use codemap;
@@ -202,9 +202,9 @@ pub enum NamedMatch {
 }
 
 pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc<NamedMatch>])
-            -> HashMap<Ident, Rc<NamedMatch>> {
+            -> HashMap<Name, Rc<NamedMatch>> {
     fn n_rec(p_s: &ParseSess, m: &TokenTree, res: &[Rc<NamedMatch>],
-             ret_val: &mut HashMap<Ident, Rc<NamedMatch>>, idx: &mut usize) {
+             ret_val: &mut HashMap<Name, Rc<NamedMatch>>, idx: &mut usize) {
         match m {
             &TtSequence(_, ref seq) => {
                 for next_m in &seq.tts {
@@ -217,7 +217,7 @@ pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc<NamedMatch>])
                 }
             }
             &TtToken(sp, MatchNt(bind_name, _, _, _)) => {
-                match ret_val.entry(bind_name) {
+                match ret_val.entry(bind_name.name) {
                     Vacant(spot) => {
                         spot.insert(res[*idx].clone());
                         *idx += 1;
@@ -246,7 +246,7 @@ pub enum ParseResult<T> {
     Error(codemap::Span, String)
 }
 
-pub type NamedParseResult = ParseResult<HashMap<Ident, Rc<NamedMatch>>>;
+pub type NamedParseResult = ParseResult<HashMap<Name, Rc<NamedMatch>>>;
 pub type PositionalParseResult = ParseResult<Vec<Rc<NamedMatch>>>;
 
 /// Perform a token equality check, ignoring syntax context (that is, an
index d728fa59bd1df3e02aa2047b5ea49d5ea367feeb..cce4450b2991af814a9f0b95a920a93a97f42710 100644 (file)
@@ -282,7 +282,7 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
     };
 
     // Extract the arguments:
-    let lhses = match **argument_map.get(&lhs_nm).unwrap() {
+    let lhses = match **argument_map.get(&lhs_nm.name).unwrap() {
         MatchedSeq(ref s, _) => /* FIXME (#2543) */ (*s).clone(),
         _ => cx.span_bug(def.span, "wrong-structured lhs")
     };
@@ -291,7 +291,7 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
         check_lhs_nt_follows(cx, &**lhs, def.span);
     }
 
-    let rhses = match **argument_map.get(&rhs_nm).unwrap() {
+    let rhses = match **argument_map.get(&rhs_nm.name).unwrap() {
         MatchedSeq(ref s, _) => /* FIXME (#2543) */ (*s).clone(),
         _ => cx.span_bug(def.span, "wrong-structured rhs")
     };
@@ -497,7 +497,7 @@ fn is_in_follow(_: &ExtCtxt, tok: &Token, frag: &str) -> Result<bool, String> {
                 Ok(true)
             },
             "block" => {
-                // anything can follow block, the braces provide a easy boundary to
+                // anything can follow block, the braces provide an easy boundary to
                 // maintain
                 Ok(true)
             },
@@ -510,14 +510,14 @@ fn is_in_follow(_: &ExtCtxt, tok: &Token, frag: &str) -> Result<bool, String> {
             "pat" => {
                 match *tok {
                     FatArrow | Comma | Eq => Ok(true),
-                    Ident(i, _) if i.name == "if" || i.name == "in" => Ok(true),
+                    Ident(i, _) if i.name.as_str() == "if" || i.name.as_str() == "in" => Ok(true),
                     _ => Ok(false)
                 }
             },
             "path" | "ty" => {
                 match *tok {
                     Comma | FatArrow | Colon | Eq | Gt | Semi => Ok(true),
-                    Ident(i, _) if i.name == "as" => Ok(true),
+                    Ident(i, _) if i.name.as_str() == "as" => Ok(true),
                     _ => Ok(false)
                 }
             },
index b07bd099638642d556fa3c461cf44428009106cb..d1e48eda4ffd2f46b774fe6c3e5e39dd022767df 100644 (file)
@@ -10,7 +10,7 @@
 use self::LockstepIterSize::*;
 
 use ast;
-use ast::{TokenTree, TtDelimited, TtToken, TtSequence, Ident};
+use ast::{TokenTree, TtDelimited, TtToken, TtSequence, Ident, Name};
 use codemap::{Span, DUMMY_SP};
 use diagnostic::SpanHandler;
 use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
@@ -38,7 +38,7 @@ pub struct TtReader<'a> {
     /// the unzipped tree:
     stack: Vec<TtFrame>,
     /* for MBE-style macro transcription */
-    interpolations: HashMap<Ident, Rc<NamedMatch>>,
+    interpolations: HashMap<Name, Rc<NamedMatch>>,
     imported_from: Option<Ident>,
 
     // Some => return imported_from as the next token
@@ -56,7 +56,7 @@ pub struct TtReader<'a> {
 /// `src` contains no `TtSequence`s, `MatchNt`s or `SubstNt`s, `interp` can
 /// (and should) be None.
 pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler,
-                         interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
+                         interp: Option<HashMap<Name, Rc<NamedMatch>>>,
                          imported_from: Option<Ident>,
                          src: Vec<ast::TokenTree>)
                          -> TtReader<'a> {
@@ -70,7 +70,7 @@ pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler,
 /// `src` contains no `TtSequence`s, `MatchNt`s or `SubstNt`s, `interp` can
 /// (and should) be None.
 pub fn new_tt_reader_with_doc_flag<'a>(sp_diag: &'a SpanHandler,
-                                       interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
+                                       interp: Option<HashMap<Name, Rc<NamedMatch>>>,
                                        imported_from: Option<Ident>,
                                        src: Vec<ast::TokenTree>,
                                        desugar_doc_comments: bool)
@@ -117,7 +117,7 @@ fn lookup_cur_matched_by_matched(r: &TtReader, start: Rc<NamedMatch>) -> Rc<Name
 }
 
 fn lookup_cur_matched(r: &TtReader, name: Ident) -> Option<Rc<NamedMatch>> {
-    let matched_opt = r.interpolations.get(&name).cloned();
+    let matched_opt = r.interpolations.get(&name.name).cloned();
     matched_opt.map(|s| lookup_cur_matched_by_matched(r, s))
 }
 
index abc04102950557e972e05b66405865021960fe51..a0c089aff217225ad7d8664057322d27b1b1a083 100644 (file)
@@ -35,7 +35,7 @@ use codemap::{CodeMap, Span};
 use diagnostic::SpanHandler;
 use visit;
 use visit::{FnKind, Visitor};
-use parse::token::{self, InternedString};
+use parse::token::InternedString;
 
 use std::ascii::AsciiExt;
 use std::cmp;
@@ -81,8 +81,8 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option<u32>, Status
     ("associated_types", "1.0.0", None, Accepted),
     ("visible_private_types", "1.0.0", None, Active),
     ("slicing_syntax", "1.0.0", None, Accepted),
-    ("box_syntax", "1.0.0", None, Active),
-    ("placement_in_syntax", "1.0.0", None, Active),
+    ("box_syntax", "1.0.0", Some(27779), Active),
+    ("placement_in_syntax", "1.0.0", Some(27779), Active),
     ("pushpop_unsafe", "1.2.0", None, Active),
     ("on_unimplemented", "1.0.0", None, Active),
     ("simd_ffi", "1.0.0", None, Active),
@@ -136,6 +136,10 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option<u32>, Status
     // switch to Accepted; see RFC 320)
     ("unsafe_no_drop_flag", "1.0.0", None, Active),
 
+    // Allows using the unsafe_destructor_blind_to_params attribute;
+    // RFC 1238
+    ("dropck_parametricity", "1.3.0", Some(28498), Active),
+
     // Allows the use of custom attributes; RFC 572
     ("custom_attribute", "1.0.0", None, Active),
 
@@ -191,6 +195,21 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option<u32>, Status
 
     // allow `#[unwind]`
     ("unwind_attributes", "1.4.0", None, Active),
+
+    // allow empty structs and enum variants with braces
+    ("braced_empty_structs", "1.5.0", None, Active),
+
+    // allow overloading augmented assignment operations like `a += b`
+    ("augmented_assignments", "1.5.0", None, Active),
+
+    // allow `#[no_debug]`
+    ("no_debug", "1.5.0", None, Active),
+
+    // allow `#[omit_gdb_pretty_printer_section]`
+    ("omit_gdb_pretty_printer_section", "1.5.0", None, Active),
+
+    // Allows cfg(target_vendor = "...").
+    ("cfg_target_vendor", "1.5.0", None, Active),
 ];
 // (changing above list without updating src/doc/reference.md makes @cmr sad)
 
@@ -314,11 +333,21 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat
     ("link_section", Whitelisted, Ungated),
     ("no_builtins", Whitelisted, Ungated),
     ("no_mangle", Whitelisted, Ungated),
-    ("no_debug", Whitelisted, Ungated),
-    ("omit_gdb_pretty_printer_section", Whitelisted, Ungated),
+    ("no_debug", Whitelisted, Gated("no_debug",
+                                    "the `#[no_debug]` attribute \
+                                     is an experimental feature")),
+    ("omit_gdb_pretty_printer_section", Whitelisted, Gated("omit_gdb_pretty_printer_section",
+                                                       "the `#[omit_gdb_pretty_printer_section]` \
+                                                        attribute is just used for the Rust test \
+                                                        suite")),
     ("unsafe_no_drop_flag", Whitelisted, Gated("unsafe_no_drop_flag",
                                                "unsafe_no_drop_flag has unstable semantics \
                                                 and may be removed in the future")),
+    ("unsafe_destructor_blind_to_params",
+     Normal,
+     Gated("dropck_parametricity",
+           "unsafe_destructor_blind_to_params has unstable semantics \
+            and may be removed in the future")),
     ("unwind", Whitelisted, Gated("unwind_attributes", "#[unwind] is experimental")),
 
     // used in resolve
@@ -360,6 +389,7 @@ macro_rules! cfg_fn {
 const GATED_CFGS: &'static [(&'static str, &'static str, fn(&Features) -> bool)] = &[
     // (name in cfg, feature, function to check if the feature is enabled)
     ("target_feature", "cfg_target_feature", cfg_fn!(|x| x.cfg_target_feature)),
+    ("target_vendor", "cfg_target_vendor", cfg_fn!(|x| x.cfg_target_vendor)),
 ];
 
 #[derive(Debug, Eq, PartialEq)]
@@ -454,6 +484,9 @@ pub struct Features {
     pub default_type_parameter_fallback: bool,
     pub type_macros: bool,
     pub cfg_target_feature: bool,
+    pub cfg_target_vendor: bool,
+    pub augmented_assignments: bool,
+    pub braced_empty_structs: bool,
 }
 
 impl Features {
@@ -482,6 +515,9 @@ impl Features {
             default_type_parameter_fallback: false,
             type_macros: false,
             cfg_target_feature: false,
+            cfg_target_vendor: false,
+            augmented_assignments: false,
+            braced_empty_structs: false,
         }
     }
 }
@@ -647,8 +683,8 @@ struct MacroVisitor<'a> {
 
 impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
     fn visit_mac(&mut self, mac: &ast::Mac) {
-        let ast::MacInvocTT(ref path, _, _) = mac.node;
-        let id = path.segments.last().unwrap().identifier;
+        let path = &mac.node.path;
+        let name = path.segments.last().unwrap().identifier.name.as_str();
 
         // Issue 22234: If you add a new case here, make sure to also
         // add code to catch the macro during or after expansion.
@@ -658,19 +694,19 @@ impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
         // catch uses of these macros within conditionally-compiled
         // code, e.g. `#[cfg]`-guarded functions.
 
-        if id == token::str_to_ident("asm") {
+        if name == "asm" {
             self.context.gate_feature("asm", path.span, EXPLAIN_ASM);
         }
 
-        else if id == token::str_to_ident("log_syntax") {
+        else if name == "log_syntax" {
             self.context.gate_feature("log_syntax", path.span, EXPLAIN_LOG_SYNTAX);
         }
 
-        else if id == token::str_to_ident("trace_macros") {
+        else if name == "trace_macros" {
             self.context.gate_feature("trace_macros", path.span, EXPLAIN_TRACE_MACROS);
         }
 
-        else if id == token::str_to_ident("concat_idents") {
+        else if name == "concat_idents" {
             self.context.gate_feature("concat_idents", path.span, EXPLAIN_CONCAT_IDENTS);
         }
     }
@@ -688,11 +724,11 @@ impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
         // But we keep these checks as a pre-expansion check to catch
         // uses in e.g. conditionalized code.
 
-        if let ast::ExprBox(None, _) = e.node {
+        if let ast::ExprBox(_) = e.node {
             self.context.gate_feature("box_syntax", e.span, EXPLAIN_BOX_SYNTAX);
         }
 
-        if let ast::ExprBox(Some(_), _) = e.node {
+        if let ast::ExprInPlace(..) = e.node {
             self.context.gate_feature("placement_in_syntax", e.span, EXPLAIN_PLACEMENT_IN);
         }
 
@@ -701,7 +737,7 @@ impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
 }
 
 struct PostExpansionVisitor<'a> {
-    context: &'a Context<'a>
+    context: &'a Context<'a>,
 }
 
 impl<'a> PostExpansionVisitor<'a> {
@@ -821,6 +857,21 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
         visit::walk_item(self, i);
     }
 
+    fn visit_variant_data(&mut self, s: &'v ast::VariantData, _: ast::Ident,
+                        _: &'v ast::Generics, _: ast::NodeId, span: Span) {
+        if s.fields().is_empty() {
+            if s.is_struct() {
+                self.gate_feature("braced_empty_structs", span,
+                                  "empty structs and enum variants with braces are unstable");
+            } else if s.is_tuple() {
+                self.context.span_handler.span_err(span, "empty tuple structs and enum variants \
+                                                          are not allowed, use unit structs and \
+                                                          enum variants instead");
+            }
+        }
+        visit::walk_struct_def(self, s)
+    }
+
     fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
         let links_to_llvm = match attr::first_attr_value_str_by_name(&i.attrs,
                                                                      "link_name") {
@@ -837,7 +888,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
 
     fn visit_expr(&mut self, e: &ast::Expr) {
         match e.node {
-            ast::ExprBox(..) | ast::ExprUnary(ast::UnOp::UnUniq, _) => {
+            ast::ExprBox(_) => {
                 self.gate_feature("box_syntax",
                                   e.span,
                                   "box expression syntax is experimental; \
@@ -1034,6 +1085,9 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
         default_type_parameter_fallback: cx.has_feature("default_type_parameter_fallback"),
         type_macros: cx.has_feature("type_macros"),
         cfg_target_feature: cx.has_feature("cfg_target_feature"),
+        cfg_target_vendor: cx.has_feature("cfg_target_vendor"),
+        augmented_assignments: cx.has_feature("augmented_assignments"),
+        braced_empty_structs: cx.has_feature("braced_empty_structs"),
     }
 }
 
@@ -1064,8 +1118,7 @@ pub enum UnstableFeatures {
     /// Errors are bypassed for bootstrapping. This is required any time
     /// during the build that feature-related lints are set to warn or above
     /// because the build turns on warnings-as-errors and uses lots of unstable
-    /// features. As a result, this this is always required for building Rust
-    /// itself.
+    /// features. As a result, this is always required for building Rust itself.
     Cheat
 }
 
index 0cfddc9857c67199d13afd9d739d99bd9e78ce8a..be910285db356f65b9a67dade99d481b7c6616b3 100644 (file)
@@ -231,8 +231,8 @@ pub trait Folder : Sized {
         noop_fold_poly_trait_ref(p, self)
     }
 
-    fn fold_struct_def(&mut self, struct_def: P<StructDef>) -> P<StructDef> {
-        noop_fold_struct_def(struct_def, self)
+    fn fold_variant_data(&mut self, vdata: VariantData) -> VariantData {
+        noop_fold_variant_data(vdata, self)
     }
 
     fn fold_lifetimes(&mut self, lts: Vec<Lifetime>) -> Vec<Lifetime> {
@@ -271,10 +271,6 @@ pub trait Folder : Sized {
         noop_fold_opt_lifetime(o_lt, self)
     }
 
-    fn fold_variant_arg(&mut self, va: VariantArg) -> VariantArg {
-        noop_fold_variant_arg(va, self)
-    }
-
     fn fold_opt_bounds(&mut self, b: Option<OwnedSlice<TyParamBound>>)
                        -> Option<OwnedSlice<TyParamBound>> {
         noop_fold_opt_bounds(b, self)
@@ -450,22 +446,12 @@ pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, items}: ForeignMod,
 }
 
 pub fn noop_fold_variant<T: Folder>(v: P<Variant>, fld: &mut T) -> P<Variant> {
-    v.map(|Spanned {node: Variant_ {id, name, attrs, kind, disr_expr, vis}, span}| Spanned {
+    v.map(|Spanned {node: Variant_ {name, attrs, data, disr_expr}, span}| Spanned {
         node: Variant_ {
-            id: fld.new_id(id),
             name: name,
             attrs: fold_attrs(attrs, fld),
-            kind: match kind {
-                TupleVariantKind(variant_args) => {
-                    TupleVariantKind(variant_args.move_map(|x|
-                        fld.fold_variant_arg(x)))
-                }
-                StructVariantKind(struct_def) => {
-                    StructVariantKind(fld.fold_struct_def(struct_def))
-                }
-            },
+            data: fld.fold_variant_data(data),
             disr_expr: disr_expr.map(|e| fld.fold_expr(e)),
-            vis: vis,
         },
         span: fld.new_span(span),
     })
@@ -568,10 +554,10 @@ pub fn noop_fold_explicit_self<T: Folder>(Spanned {span, node}: ExplicitSelf, fl
 
 pub fn noop_fold_mac<T: Folder>(Spanned {node, span}: Mac, fld: &mut T) -> Mac {
     Spanned {
-        node: match node {
-            MacInvocTT(p, tts, ctxt) => {
-                MacInvocTT(fld.fold_path(p), fld.fold_tts(&tts), ctxt)
-            }
+        node: Mac_ {
+            path: fld.fold_path(node.path),
+            tts: fld.fold_tts(&node.tts),
+            ctxt: node.ctxt,
         },
         span: fld.new_span(span)
     }
@@ -828,11 +814,18 @@ pub fn noop_fold_where_predicate<T: Folder>(
     }
 }
 
-pub fn noop_fold_struct_def<T: Folder>(struct_def: P<StructDef>, fld: &mut T) -> P<StructDef> {
-    struct_def.map(|StructDef { fields, ctor_id }| StructDef {
-        fields: fields.move_map(|f| fld.fold_struct_field(f)),
-        ctor_id: ctor_id.map(|cid| fld.new_id(cid)),
-    })
+pub fn noop_fold_variant_data<T: Folder>(vdata: VariantData, fld: &mut T) -> VariantData {
+    match vdata {
+        ast::VariantData::Struct(fields, id) => {
+            ast::VariantData::Struct(fields.move_map(|f| fld.fold_struct_field(f)),
+                                     fld.new_id(id))
+        }
+        ast::VariantData::Tuple(fields, id) => {
+            ast::VariantData::Tuple(fields.move_map(|f| fld.fold_struct_field(f)),
+                                    fld.new_id(id))
+        }
+        ast::VariantData::Unit(id) => ast::VariantData::Unit(fld.new_id(id))
+    }
 }
 
 pub fn noop_fold_trait_ref<T: Folder>(p: TraitRef, fld: &mut T) -> TraitRef {
@@ -893,14 +886,6 @@ fn noop_fold_bounds<T: Folder>(bounds: TyParamBounds, folder: &mut T)
     bounds.move_map(|bound| folder.fold_ty_param_bound(bound))
 }
 
-fn noop_fold_variant_arg<T: Folder>(VariantArg {id, ty}: VariantArg, folder: &mut T)
-                                    -> VariantArg {
-    VariantArg {
-        id: folder.new_id(id),
-        ty: folder.fold_ty(ty)
-    }
-}
-
 pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
     b.map(|Block {id, stmts, expr, rules, span}| Block {
         id: folder.new_id(id),
@@ -946,7 +931,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
                 folder.fold_generics(generics))
         }
         ItemStruct(struct_def, generics) => {
-            let struct_def = folder.fold_struct_def(struct_def);
+            let struct_def = folder.fold_variant_data(struct_def);
             ItemStruct(struct_def, folder.fold_generics(generics))
         }
         ItemDefaultImpl(unsafety, ref trait_ref) => {
@@ -1189,8 +1174,11 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
     Expr {
         id: folder.new_id(id),
         node: match node {
-            ExprBox(p, e) => {
-                ExprBox(p.map(|e|folder.fold_expr(e)), folder.fold_expr(e))
+            ExprBox(e) => {
+                ExprBox(folder.fold_expr(e))
+            }
+            ExprInPlace(p, e) => {
+                ExprInPlace(folder.fold_expr(p), folder.fold_expr(e))
             }
             ExprVec(exprs) => {
                 ExprVec(exprs.move_map(|x| folder.fold_expr(x)))
@@ -1254,10 +1242,9 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
                 ExprLoop(folder.fold_block(body),
                         opt_ident.map(|i| folder.fold_ident(i)))
             }
-            ExprMatch(expr, arms, source) => {
+            ExprMatch(expr, arms) => {
                 ExprMatch(folder.fold_expr(expr),
-                        arms.move_map(|x| folder.fold_arm(x)),
-                        source)
+                          arms.move_map(|x| folder.fold_arm(x)))
             }
             ExprClosure(capture_clause, decl, body) => {
                 ExprClosure(capture_clause,
index d1c862ad40b2526866fd0e52be4cd2a626ee04c7..9adef08771d06fa32a297a943d4bbf3e37baf448 100644 (file)
@@ -29,7 +29,6 @@
 #![feature(drain)]
 #![feature(filling_drop)]
 #![feature(libc)]
-#![feature(ref_slice)]
 #![feature(rustc_private)]
 #![feature(set_stdio)]
 #![feature(staged_api)]
@@ -37,7 +36,6 @@
 #![feature(str_escape)]
 #![feature(unicode)]
 #![feature(vec_push_all)]
-#![feature(vec_resize)]
 
 extern crate fmt_macros;
 extern crate serialize;
@@ -121,7 +119,6 @@ pub mod ext {
     pub mod log_syntax;
     pub mod mtwt;
     pub mod quote;
-    pub mod pushpop_safe;
     pub mod source_util;
     pub mod trace_macros;
 
index 25f1f9b8480a1204d71129325688b6f1d43c72be..83369689a94de077efbce2a8ce81ff6e32c4751e 100644 (file)
@@ -12,6 +12,7 @@ use std::default::Default;
 use std::fmt;
 use std::iter::{IntoIterator, FromIterator};
 use std::ops::Deref;
+use std::slice;
 use std::vec;
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 
@@ -82,6 +83,14 @@ impl<T> FromIterator<T> for OwnedSlice<T> {
     }
 }
 
+impl<'a, T> IntoIterator for &'a OwnedSlice<T> {
+    type Item = &'a T;
+    type IntoIter = slice::Iter<'a, T>;
+    fn into_iter(self) -> Self::IntoIter {
+        self.data.into_iter()
+    }
+}
+
 impl<T: Encodable> Encodable for OwnedSlice<T> {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         Encodable::encode(&**self, s)
index 18588c59357b29c9d0e056474ee61caf3bf408cf..219360093d14605c4b170d298b7812b1c168d33b 100644 (file)
@@ -40,11 +40,11 @@ impl<'a> ParserAttr for Parser<'a> {
               token::DocComment(s) => {
                 let attr = ::attr::mk_sugared_doc_attr(
                     attr::mk_attr_id(),
-                    self.id_to_interned_str(s.ident()),
+                    self.id_to_interned_str(ast::Ident::with_empty_ctxt(s)),
                     self.span.lo,
                     self.span.hi
                 );
-                if attr.node.style != ast::AttrOuter {
+                if attr.node.style != ast::AttrStyle::Outer {
                   panic!(self.fatal("expected outer comment"));
                 }
                 attrs.push(attr);
@@ -79,9 +79,9 @@ impl<'a> ParserAttr for Parser<'a> {
                         self.fileline_help(span,
                                        "place inner attribute at the top of the module or block");
                     }
-                    ast::AttrInner
+                    ast::AttrStyle::Inner
                 } else {
-                    ast::AttrOuter
+                    ast::AttrStyle::Outer
                 };
 
                 panictry!(self.expect(&token::OpenDelim(token::Bracket)));
@@ -101,7 +101,7 @@ impl<'a> ParserAttr for Parser<'a> {
             panictry!(self.bump());
             self.span_warn(span, "this inner attribute syntax is deprecated. \
                            The new syntax is `#![foo]`, with a bang and no semicolon");
-            style = ast::AttrInner;
+            style = ast::AttrStyle::Inner;
         }
 
         return Spanned {
@@ -131,16 +131,15 @@ impl<'a> ParserAttr for Parser<'a> {
                     }
 
                     let attr = self.parse_attribute(true);
-                    assert!(attr.node.style == ast::AttrInner);
+                    assert!(attr.node.style == ast::AttrStyle::Inner);
                     attrs.push(attr);
                 }
                 token::DocComment(s) => {
                     // we need to get the position of this token before we bump.
                     let Span { lo, hi, .. } = self.span;
-                    let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(),
-                                                         self.id_to_interned_str(s.ident()),
-                                                         lo, hi);
-                    if attr.node.style == ast::AttrInner {
+                    let str = self.id_to_interned_str(ast::Ident::with_empty_ctxt(s));
+                    let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), str, lo, hi);
+                    if attr.node.style == ast::AttrStyle::Inner {
                         attrs.push(attr);
                         panictry!(self.bump());
                     } else {
index 9033208fbdbdcea336c0bfdc37a61875c5a9cccb..137996a35ee8f57cb119e3def16dbbe1fa8be729 100644 (file)
@@ -52,9 +52,9 @@ pub fn is_doc_comment(s: &str) -> bool {
 pub fn doc_comment_style(comment: &str) -> ast::AttrStyle {
     assert!(is_doc_comment(comment));
     if comment.starts_with("//!") || comment.starts_with("/*!") {
-        ast::AttrInner
+        ast::AttrStyle::Inner
     } else {
-        ast::AttrOuter
+        ast::AttrStyle::Outer
     }
 }
 
index a0e170b4ace466fa5a28e40ce3ce71a213e62139..490822b934e5ed314a9d68946499f9bb4f31600f 100644 (file)
@@ -1385,8 +1385,9 @@ pub fn is_doc_comment(s: &str) -> bool {
 }
 
 pub fn is_block_doc_comment(s: &str) -> bool {
-    let res = (s.starts_with("/**") && *s.as_bytes().get(3).unwrap_or(&b' ') != b'*')
-              || s.starts_with("/*!");
+    let res = ((s.starts_with("/**") && *s.as_bytes().get(3).unwrap_or(&b' ') != b'*')
+               || s.starts_with("/*!"))
+              && s.len() >= 5; // Prevent `/**/` from being parsed as a doc comment
     debug!("is {:?} a doc comment? {}", s, res);
     res
 }
index 269f8bdd98acc45b4f1ef6dc294a6353223b0a2c..5beec702f8cfb1ab08412bc32a898debab885e86 100644 (file)
@@ -744,8 +744,8 @@ mod tests {
                 Some(&ast::TtToken(_, token::Ident(name_zip, token::Plain))),
                 Some(&ast::TtDelimited(_, ref macro_delimed)),
             )
-            if name_macro_rules.name == "macro_rules"
-            && name_zip.name == "zip" => {
+            if name_macro_rules.name.as_str() == "macro_rules"
+            && name_zip.name.as_str() == "zip" => {
                 let tts = &macro_delimed.tts[..];
                 match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) {
                     (
@@ -763,7 +763,7 @@ mod tests {
                                 Some(&ast::TtToken(_, token::Ident(ident, token::Plain))),
                             )
                             if first_delimed.delim == token::Paren
-                            && ident.name == "a" => {},
+                            && ident.name.as_str() == "a" => {},
                             _ => panic!("value 3: {:?}", **first_delimed),
                         }
                         let tts = &second_delimed.tts[..];
@@ -774,7 +774,7 @@ mod tests {
                                 Some(&ast::TtToken(_, token::Ident(ident, token::Plain))),
                             )
                             if second_delimed.delim == token::Paren
-                            && ident.name == "a" => {},
+                            && ident.name.as_str() == "a" => {},
                             _ => panic!("value 4: {:?}", **second_delimed),
                         }
                     },
@@ -1090,10 +1090,7 @@ mod tests {
             "foo!( fn main() { body } )".to_string(), vec![], &sess);
 
         let tts = match expr.node {
-            ast::ExprMac(ref mac) => {
-                let ast::MacInvocTT(_, ref tts, _) = mac.node;
-                tts.clone()
-            }
+            ast::ExprMac(ref mac) => mac.node.tts.clone(),
             _ => panic!("not a macro"),
         };
 
index 8d50cc099bd60ae1e34e9c02335098945e95ef43..e153f1665e3e6db32ce9327fcf5069c2b1e0cbb6 100644 (file)
@@ -22,7 +22,7 @@ use ast::{Decl, DeclItem, DeclLocal, DefaultBlock, DefaultReturn};
 use ast::{UnDeref, BiDiv, EMPTY_CTXT, EnumDef, ExplicitSelf};
 use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
 use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox};
-use ast::{ExprBreak, ExprCall, ExprCast};
+use ast::{ExprBreak, ExprCall, ExprCast, ExprInPlace};
 use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex};
 use ast::{ExprLit, ExprLoop, ExprMac, ExprRange};
 use ast::{ExprMethodCall, ExprParen, ExprPath};
@@ -37,7 +37,7 @@ use ast::{LifetimeDef, Lit, Lit_};
 use ast::{LitBool, LitChar, LitByte, LitByteStr};
 use ast::{LitStr, LitInt, Local};
 use ast::{MacStmtWithBraces, MacStmtWithSemicolon, MacStmtWithoutBraces};
-use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, MatchSource};
+use ast::{MutImmutable, MutMutable, Mac_};
 use ast::{MutTy, BiMul, Mutability};
 use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, UnNot};
 use ast::{Pat, PatBox, PatEnum, PatIdent, PatLit, PatQPath, PatMac, PatRange};
@@ -45,16 +45,16 @@ use ast::{PatRegion, PatStruct, PatTup, PatVec, PatWild, PatWildMulti};
 use ast::PatWildSingle;
 use ast::{PolyTraitRef, QSelf};
 use ast::{Return, BiShl, BiShr, Stmt, StmtDecl};
-use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
-use ast::{StructVariantKind, BiSub, StrStyle};
+use ast::{StmtExpr, StmtSemi, StmtMac, VariantData, StructField};
+use ast::{BiSub, StrStyle};
 use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue};
 use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef};
 use ast::{TtDelimited, TtSequence, TtToken};
-use ast::{TupleVariantKind, Ty, Ty_, TypeBinding};
+use ast::{Ty, Ty_, TypeBinding};
 use ast::{TyMac};
 use ast::{TyFixedLengthVec, TyBareFn, TyTypeof, TyInfer};
 use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr};
-use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq};
+use ast::{TyRptr, TyTup, TyU32, TyVec};
 use ast::{TypeImplItem, TypeTraitItem};
 use ast::{UnnamedField, UnsafeBlock};
 use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
@@ -422,7 +422,7 @@ impl<'a> Parser<'a> {
                                    this_token_str)))
             }
         } else {
-            self.expect_one_of(slice::ref_slice(t), &[])
+            self.expect_one_of(unsafe { slice::from_raw_parts(t, 1) }, &[])
         }
     }
 
@@ -1263,7 +1263,7 @@ impl<'a> Parser<'a> {
     pub fn parse_ret_ty(&mut self) -> PResult<FunctionRetTy> {
         if try!(self.eat(&token::RArrow) ){
             if try!(self.eat(&token::Not) ){
-                Ok(NoReturn(self.span))
+                Ok(NoReturn(self.last_span))
             } else {
                 Ok(Return(try!(self.parse_ty_nopanic())))
             }
@@ -1381,7 +1381,7 @@ impl<'a> Parser<'a> {
                                                      seq_sep_none(),
                                                      |p| p.parse_token_tree()));
                 let hi = self.span.hi;
-                TyMac(spanned(lo, hi, MacInvocTT(path, tts, EMPTY_CTXT)))
+                TyMac(spanned(lo, hi, Mac_ { path: path, tts: tts, ctxt: EMPTY_CTXT }))
             } else {
                 // NAMED TYPE
                 TyPath(None, path)
@@ -1583,11 +1583,11 @@ impl<'a> Parser<'a> {
 
         let lo = self.span.lo;
         let literal = P(try!(self.parse_lit()));
-        let hi = self.span.hi;
+        let hi = self.last_span.hi;
         let expr = self.mk_expr(lo, hi, ExprLit(literal));
 
         if minus_present {
-            let minus_hi = self.span.hi;
+            let minus_hi = self.last_span.hi;
             let unary = self.mk_unary(UnNeg, expr);
             Ok(self.mk_expr(minus_lo, minus_hi, unary))
         } else {
@@ -1595,8 +1595,21 @@ impl<'a> Parser<'a> {
         }
     }
 
-    // QUALIFIED PATH `<TYPE [as TRAIT_REF]>::IDENT[::<PARAMS>]`
-    // Assumes that the leading `<` has been parsed already.
+    /// Parses qualified path.
+    ///
+    /// Assumes that the leading `<` has been parsed already.
+    ///
+    /// Qualifed paths are a part of the universal function call
+    /// syntax (UFCS).
+    ///
+    /// `qualified_path = <type [as trait_ref]>::path`
+    ///
+    /// See `parse_path` for `mode` meaning.
+    ///
+    /// # Examples:
+    ///
+    /// `<T as U>::a`
+    /// `<T as U>::F::a::<S>`
     pub fn parse_qualified_path(&mut self, mode: PathParsingMode)
                                 -> PResult<(QSelf, ast::Path)> {
         let span = self.last_span;
@@ -2203,9 +2216,7 @@ impl<'a> Parser<'a> {
 
                         return Ok(self.mk_mac_expr(lo,
                                                    hi,
-                                                   MacInvocTT(pth,
-                                                              tts,
-                                                              EMPTY_CTXT)));
+                                                   Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT }));
                     }
                     if self.check(&token::OpenDelim(token::Brace)) {
                         // This is a struct literal, unless we're prohibited
@@ -2231,14 +2242,6 @@ impl<'a> Parser<'a> {
                                                  &[token::CloseDelim(token::Brace)]));
                             }
 
-                            if fields.is_empty() && base.is_none() {
-                                let last_span = self.last_span;
-                                self.span_err(last_span,
-                                              "structure literal must either \
-                                              have at least one field or use \
-                                              structure update syntax");
-                            }
-
                             hi = self.span.hi;
                             try!(self.expect(&token::CloseDelim(token::Brace)));
                             ex = ExprStruct(pth, fields, base);
@@ -2627,76 +2630,19 @@ impl<'a> Parser<'a> {
             hi = e.span.hi;
             ex = ExprAddrOf(m, e);
           }
-          token::Ident(_, _) => {
-            if !self.check_keyword(keywords::Box) && !self.check_keyword(keywords::In) {
-                return self.parse_dot_or_call_expr();
-            }
-
-            let lo = self.span.lo;
-            let keyword_hi = self.span.hi;
-
-            let is_in = self.token.is_keyword(keywords::In);
-            try!(self.bump());
-
-            if is_in {
+          token::Ident(..) if self.token.is_keyword(keywords::In) => {
+              try!(self.bump());
               let place = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
               let blk = try!(self.parse_block());
               hi = blk.span.hi;
               let blk_expr = self.mk_expr(blk.span.lo, blk.span.hi, ExprBlock(blk));
-              ex = ExprBox(Some(place), blk_expr);
-              return Ok(self.mk_expr(lo, hi, ex));
-            }
-
-            // FIXME (#22181) Remove `box (PLACE) EXPR` support
-            // entirely after next release (enabling `(box (EXPR))`),
-            // since it will be replaced by `in PLACE { EXPR }`, ...
-            //
-            // ... but for now: check for a place: `box(PLACE) EXPR`.
-
-            if try!(self.eat(&token::OpenDelim(token::Paren))) {
-                let box_span = mk_sp(lo, self.last_span.hi);
-                self.span_warn(box_span,
-                    "deprecated syntax; use the `in` keyword now \
-                           (e.g. change `box (<expr>) <expr>` to \
-                                        `in <expr> { <expr> }`)");
-
-                // Continue supporting `box () EXPR` (temporarily)
-                if !try!(self.eat(&token::CloseDelim(token::Paren))) {
-                    let place = try!(self.parse_expr_nopanic());
-                    try!(self.expect(&token::CloseDelim(token::Paren)));
-                    // Give a suggestion to use `box()` when a parenthesised expression is used
-                    if !self.token.can_begin_expr() {
-                        let span = self.span;
-                        let this_token_to_string = self.this_token_to_string();
-                        self.span_err(span,
-                                      &format!("expected expression, found `{}`",
-                                              this_token_to_string));
-
-                        // Spanning just keyword avoids constructing
-                        // printout of arg expression (which starts
-                        // with parenthesis, as established above).
-
-                        let box_span = mk_sp(lo, keyword_hi);
-                        self.span_suggestion(box_span,
-                                             "try using `box ()` instead:",
-                                             format!("box ()"));
-                        self.abort_if_errors();
-                    }
-                    let subexpression = try!(self.parse_prefix_expr());
-                    hi = subexpression.span.hi;
-                    ex = ExprBox(Some(place), subexpression);
-                    return Ok(self.mk_expr(lo, hi, ex));
-                }
-            }
-
-            // Otherwise, we use the unique pointer default.
-            let subexpression = try!(self.parse_prefix_expr());
-            hi = subexpression.span.hi;
-
-            // FIXME (pnkfelix): After working out kinks with box
-            // desugaring, should be `ExprBox(None, subexpression)`
-            // instead.
-            ex = self.mk_unary(UnUniq, subexpression);
+              ex = ExprInPlace(place, blk_expr);
+          }
+          token::Ident(..) if self.token.is_keyword(keywords::Box) => {
+              try!(self.bump());
+              let subexpression = try!(self.parse_prefix_expr());
+              hi = subexpression.span.hi;
+              ex = ExprBox(subexpression);
           }
           _ => return self.parse_dot_or_call_expr()
         }
@@ -2994,7 +2940,7 @@ impl<'a> Parser<'a> {
         }
         let hi = self.span.hi;
         try!(self.bump());
-        return Ok(self.mk_expr(lo, hi, ExprMatch(discriminant, arms, MatchSource::Normal)));
+        return Ok(self.mk_expr(lo, hi, ExprMatch(discriminant, arms)));
     }
 
     pub fn parse_arm_nopanic(&mut self) -> PResult<Arm> {
@@ -3250,6 +3196,10 @@ impl<'a> Parser<'a> {
             // Parse &pat / &mut pat
             try!(self.expect_and());
             let mutbl = try!(self.parse_mutability());
+            if let token::Lifetime(ident) = self.token {
+                return Err(self.fatal(&format!("unexpected lifetime `{}` in pattern", ident)));
+            }
+
             let subpat = try!(self.parse_pat_nopanic());
             pat = PatRegion(subpat, mutbl);
           }
@@ -3297,7 +3247,7 @@ impl<'a> Parser<'a> {
                         let delim = try!(self.expect_open_delim());
                         let tts = try!(self.parse_seq_to_end(&token::CloseDelim(delim),
                                 seq_sep_none(), |p| p.parse_token_tree()));
-                        let mac = MacInvocTT(path, tts, EMPTY_CTXT);
+                        let mac = Mac_ { path: path, tts: tts, ctxt: EMPTY_CTXT };
                         pat = PatMac(codemap::Spanned {node: mac, span: self.span});
                     } else {
                         // Parse ident @ pat
@@ -3326,12 +3276,9 @@ impl<'a> Parser<'a> {
                       }
                       token::OpenDelim(token::Brace) => {
                          if qself.is_some() {
-                            let span = self.span;
-                            self.span_err(span,
-                                          "unexpected `{` after qualified path");
-                            self.abort_if_errors();
+                            return Err(self.fatal("unexpected `{` after qualified path"));
                         }
-                       // Parse struct pattern
+                        // Parse struct pattern
                         try!(self.bump());
                         let (fields, etc) = try!(self.parse_pat_fields());
                         try!(self.bump());
@@ -3339,10 +3286,7 @@ impl<'a> Parser<'a> {
                       }
                       token::OpenDelim(token::Paren) => {
                         if qself.is_some() {
-                            let span = self.span;
-                            self.span_err(span,
-                                          "unexpected `(` after qualified path");
-                            self.abort_if_errors();
+                            return Err(self.fatal("unexpected `(` after qualified path"));
                         }
                         // Parse tuple struct or enum pattern
                         if self.look_ahead(1, |t| *t == token::DotDot) {
@@ -3360,13 +3304,13 @@ impl<'a> Parser<'a> {
                             pat = PatEnum(path, Some(args));
                         }
                       }
-                      _ if qself.is_some() => {
-                        // Parse qualified path
-                        pat = PatQPath(qself.unwrap(), path);
-                      }
                       _ => {
-                        // Parse nullary enum
-                        pat = PatEnum(path, Some(vec![]));
+                        pat = match qself {
+                            // Parse qualified path
+                            Some(qself) => PatQPath(qself, path),
+                            // Parse nullary enum
+                            None => PatEnum(path, Some(vec![]))
+                        };
                       }
                     }
                 }
@@ -3565,7 +3509,7 @@ impl<'a> Parser<'a> {
                 spanned(lo, hi,
                         StmtMac(P(spanned(lo,
                                           hi,
-                                          MacInvocTT(pth, tts, EMPTY_CTXT))),
+                                          Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT })),
                                   style))
             } else {
                 // if it has a special ident, it's definitely an item
@@ -3584,7 +3528,8 @@ impl<'a> Parser<'a> {
                     P(spanned(lo, hi, DeclItem(
                         self.mk_item(
                             lo, hi, id /*id is good here*/,
-                            ItemMac(spanned(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT))),
+                            ItemMac(spanned(lo, hi,
+                                            Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT })),
                             Inherited, Vec::new(/*no attrs*/))))),
                     ast::DUMMY_NODE_ID))
             }
@@ -4435,7 +4380,8 @@ impl<'a> Parser<'a> {
     /// true if we are looking at `const ID`, false for things like `const fn` etc
     pub fn is_const_item(&mut self) -> bool {
         self.token.is_keyword(keywords::Const) &&
-            !self.look_ahead(1, |t| t.is_keyword(keywords::Fn))
+            !self.look_ahead(1, |t| t.is_keyword(keywords::Fn)) &&
+            !self.look_ahead(1, |t| t.is_keyword(keywords::Unsafe))
     }
 
     /// parses all the "front matter" for a `fn` declaration, up to
@@ -4443,14 +4389,15 @@ impl<'a> Parser<'a> {
     ///
     /// - `const fn`
     /// - `unsafe fn`
+    /// - `const unsafe fn`
     /// - `extern fn`
     /// - etc
     pub fn parse_fn_front_matter(&mut self) -> PResult<(ast::Constness, ast::Unsafety, abi::Abi)> {
         let is_const_fn = try!(self.eat_keyword(keywords::Const));
+        let unsafety = try!(self.parse_unsafety());
         let (constness, unsafety, abi) = if is_const_fn {
-            (Constness::Const, Unsafety::Normal, abi::Rust)
+            (Constness::Const, unsafety, abi::Rust)
         } else {
-            let unsafety = try!(self.parse_unsafety());
             let abi = if try!(self.eat_keyword(keywords::Extern)) {
                 try!(self.parse_opt_abi()).unwrap_or(abi::C)
             } else {
@@ -4532,7 +4479,7 @@ impl<'a> Parser<'a> {
             let tts = try!(self.parse_seq_to_end(&token::CloseDelim(delim),
                                             seq_sep_none(),
                                             |p| p.parse_token_tree()));
-            let m_ = ast::MacInvocTT(pth, tts, EMPTY_CTXT);
+            let m_ = Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT };
             let m: ast::Mac = codemap::Spanned { node: m_,
                                                 span: mk_sp(self.span.lo,
                                                             self.span.hi) };
@@ -4706,54 +4653,41 @@ impl<'a> Parser<'a> {
         // Otherwise if we look ahead and see a paren we parse a tuple-style
         // struct.
 
-        let (fields, ctor_id) = if self.token.is_keyword(keywords::Where) {
+        let vdata = if self.token.is_keyword(keywords::Where) {
             generics.where_clause = try!(self.parse_where_clause());
             if try!(self.eat(&token::Semi)) {
                 // If we see a: `struct Foo<T> where T: Copy;` style decl.
-                (Vec::new(), Some(ast::DUMMY_NODE_ID))
+                VariantData::Unit(ast::DUMMY_NODE_ID)
             } else {
                 // If we see: `struct Foo<T> where T: Copy { ... }`
-                (try!(self.parse_record_struct_body(&class_name)), None)
+                VariantData::Struct(try!(self.parse_record_struct_body()), ast::DUMMY_NODE_ID)
             }
         // No `where` so: `struct Foo<T>;`
         } else if try!(self.eat(&token::Semi) ){
-            (Vec::new(), Some(ast::DUMMY_NODE_ID))
+            VariantData::Unit(ast::DUMMY_NODE_ID)
         // Record-style struct definition
         } else if self.token == token::OpenDelim(token::Brace) {
-            let fields = try!(self.parse_record_struct_body(&class_name));
-            (fields, None)
+            VariantData::Struct(try!(self.parse_record_struct_body()), ast::DUMMY_NODE_ID)
         // Tuple-style struct definition with optional where-clause.
         } else if self.token == token::OpenDelim(token::Paren) {
-            let fields = try!(self.parse_tuple_struct_body(&class_name, &mut generics));
-            (fields, Some(ast::DUMMY_NODE_ID))
+            VariantData::Tuple(try!(self.parse_tuple_struct_body(&mut generics)),
+                               ast::DUMMY_NODE_ID)
         } else {
             let token_str = self.this_token_to_string();
             return Err(self.fatal(&format!("expected `where`, `{{`, `(`, or `;` after struct \
                                             name, found `{}`", token_str)))
         };
 
-        Ok((class_name,
-         ItemStruct(P(ast::StructDef {
-             fields: fields,
-             ctor_id: ctor_id,
-         }), generics),
-         None))
+        Ok((class_name, ItemStruct(vdata, generics), None))
     }
 
-    pub fn parse_record_struct_body(&mut self,
-                                    class_name: &ast::Ident) -> PResult<Vec<StructField>> {
+    pub fn parse_record_struct_body(&mut self) -> PResult<Vec<StructField>> {
         let mut fields = Vec::new();
         if try!(self.eat(&token::OpenDelim(token::Brace)) ){
             while self.token != token::CloseDelim(token::Brace) {
                 fields.push(try!(self.parse_struct_decl_field(true)));
             }
 
-            if fields.is_empty() {
-                return Err(self.fatal(&format!("unit-like struct definition should be \
-                    written as `struct {};`",
-                    class_name)));
-            }
-
             try!(self.bump());
         } else {
             let token_str = self.this_token_to_string();
@@ -4766,7 +4700,6 @@ impl<'a> Parser<'a> {
     }
 
     pub fn parse_tuple_struct_body(&mut self,
-                                   class_name: &ast::Ident,
                                    generics: &mut ast::Generics)
                                    -> PResult<Vec<StructField>> {
         // This is the case where we find `struct Foo<T>(T) where T: Copy;`
@@ -4787,12 +4720,6 @@ impl<'a> Parser<'a> {
                 Ok(spanned(lo, p.span.hi, struct_field_))
             }));
 
-        if fields.is_empty() {
-            return Err(self.fatal(&format!("unit-like struct definition should be \
-                                            written as `struct {};`",
-                                           class_name)));
-        }
-
         generics.where_clause = try!(self.parse_where_clause());
         try!(self.expect(&token::Semi));
         Ok(fields)
@@ -4858,7 +4785,7 @@ impl<'a> Parser<'a> {
         let hi = if self.span == codemap::DUMMY_SP {
             inner_lo
         } else {
-            self.span.lo
+            self.last_span.hi
         };
 
         Ok(ast::Mod {
@@ -5052,9 +4979,8 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse a function declaration from a foreign module
-    fn parse_item_foreign_fn(&mut self, vis: ast::Visibility,
+    fn parse_item_foreign_fn(&mut self, vis: ast::Visibility, lo: BytePos,
                              attrs: Vec<Attribute>) -> PResult<P<ForeignItem>> {
-        let lo = self.span.lo;
         try!(self.expect_keyword(keywords::Fn));
 
         let (ident, mut generics) = try!(self.parse_fn_header());
@@ -5073,10 +4999,8 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse a static item from a foreign module
-    fn parse_item_foreign_static(&mut self, vis: ast::Visibility,
+    fn parse_item_foreign_static(&mut self, vis: ast::Visibility, lo: BytePos,
                                  attrs: Vec<Attribute>) -> PResult<P<ForeignItem>> {
-        let lo = self.span.lo;
-
         try!(self.expect_keyword(keywords::Static));
         let mutbl = try!(self.eat_keyword(keywords::Mut));
 
@@ -5185,17 +5109,14 @@ impl<'a> Parser<'a> {
 
     /// Parse a structure-like enum variant definition
     /// this should probably be renamed or refactored...
-    fn parse_struct_def(&mut self) -> PResult<P<StructDef>> {
+    fn parse_struct_def(&mut self) -> PResult<VariantData> {
         let mut fields: Vec<StructField> = Vec::new();
         while self.token != token::CloseDelim(token::Brace) {
             fields.push(try!(self.parse_struct_decl_field(false)));
         }
         try!(self.bump());
 
-        Ok(P(StructDef {
-            fields: fields,
-            ctor_id: None,
-        }))
+        Ok(VariantData::Struct(fields, ast::DUMMY_NODE_ID))
     }
 
     /// Parse the part of an "enum" decl following the '{'
@@ -5207,25 +5128,13 @@ impl<'a> Parser<'a> {
             let variant_attrs = self.parse_outer_attributes();
             let vlo = self.span.lo;
 
-            let vis = try!(self.parse_visibility());
-
-            let ident;
-            let kind;
-            let mut args = Vec::new();
+            let struct_def;
             let mut disr_expr = None;
-            ident = try!(self.parse_ident());
+            let ident = try!(self.parse_ident());
             if try!(self.eat(&token::OpenDelim(token::Brace)) ){
                 // Parse a struct variant.
                 all_nullary = false;
-                let start_span = self.span;
-                let struct_def = try!(self.parse_struct_def());
-                if struct_def.fields.is_empty() {
-                    self.span_err(start_span,
-                        &format!("unit-like struct variant should be written \
-                                 without braces, as `{},`",
-                                ident));
-                }
-                kind = StructVariantKind(struct_def);
+                struct_def = try!(self.parse_struct_def());
             } else if self.check(&token::OpenDelim(token::Paren)) {
                 all_nullary = false;
                 let arg_tys = try!(self.parse_enum_variant_seq(
@@ -5234,28 +5143,29 @@ impl<'a> Parser<'a> {
                     seq_sep_trailing_allowed(token::Comma),
                     |p| p.parse_ty_sum()
                 ));
+                let mut fields = Vec::new();
                 for ty in arg_tys {
-                    args.push(ast::VariantArg {
+                    fields.push(Spanned { span: ty.span, node: ast::StructField_ {
                         ty: ty,
+                        kind: ast::UnnamedField(ast::Inherited),
+                        attrs: Vec::new(),
                         id: ast::DUMMY_NODE_ID,
-                    });
+                    }});
                 }
-                kind = TupleVariantKind(args);
+                struct_def = ast::VariantData::Tuple(fields, ast::DUMMY_NODE_ID);
             } else if try!(self.eat(&token::Eq) ){
                 disr_expr = Some(try!(self.parse_expr_nopanic()));
                 any_disr = disr_expr.as_ref().map(|expr| expr.span);
-                kind = TupleVariantKind(args);
+                struct_def = ast::VariantData::Unit(ast::DUMMY_NODE_ID);
             } else {
-                kind = TupleVariantKind(Vec::new());
+                struct_def = ast::VariantData::Unit(ast::DUMMY_NODE_ID);
             }
 
             let vr = ast::Variant_ {
                 name: ident,
                 attrs: variant_attrs,
-                kind: kind,
-                id: ast::DUMMY_NODE_ID,
+                data: struct_def,
                 disr_expr: disr_expr,
-                vis: vis,
             };
             variants.push(P(spanned(vlo, self.last_span.hi, vr)));
 
@@ -5392,11 +5302,18 @@ impl<'a> Parser<'a> {
             return Ok(Some(item));
         }
         if try!(self.eat_keyword(keywords::Const) ){
-            if self.check_keyword(keywords::Fn) {
+            if self.check_keyword(keywords::Fn)
+                || (self.check_keyword(keywords::Unsafe)
+                    && self.look_ahead(1, |t| t.is_keyword(keywords::Fn))) {
                 // CONST FUNCTION ITEM
+                let unsafety = if try!(self.eat_keyword(keywords::Unsafe) ){
+                    Unsafety::Unsafe
+                } else {
+                    Unsafety::Normal
+                };
                 try!(self.bump());
                 let (ident, item_, extra_attrs) =
-                    try!(self.parse_item_fn(Unsafety::Normal, Constness::Const, abi::Rust));
+                    try!(self.parse_item_fn(unsafety, Constness::Const, abi::Rust));
                 let last_span = self.last_span;
                 let item = self.mk_item(lo,
                                         last_span.hi,
@@ -5576,11 +5493,11 @@ impl<'a> Parser<'a> {
 
         if self.check_keyword(keywords::Static) {
             // FOREIGN STATIC ITEM
-            return Ok(Some(try!(self.parse_item_foreign_static(visibility, attrs))));
+            return Ok(Some(try!(self.parse_item_foreign_static(visibility, lo, attrs))));
         }
         if self.check_keyword(keywords::Fn) || self.check_keyword(keywords::Unsafe) {
             // FOREIGN FUNCTION ITEM
-            return Ok(Some(try!(self.parse_item_foreign_fn(visibility, attrs))));
+            return Ok(Some(try!(self.parse_item_foreign_fn(visibility, lo, attrs))));
         }
 
         // FIXME #5668: this will occur for a macro invocation:
@@ -5628,7 +5545,7 @@ impl<'a> Parser<'a> {
                                             seq_sep_none(),
                                             |p| p.parse_token_tree()));
             // single-variant-enum... :
-            let m = ast::MacInvocTT(pth, tts, EMPTY_CTXT);
+            let m = Mac_ { path: pth, tts: tts, ctxt: EMPTY_CTXT };
             let m: ast::Mac = codemap::Spanned { node: m,
                                              span: mk_sp(self.span.lo,
                                                          self.span.hi) };
@@ -5803,10 +5720,10 @@ impl<'a> Parser<'a> {
                                                  Option<ast::Name>)>> {
         let ret = match self.token {
             token::Literal(token::Str_(s), suf) => {
-                (self.id_to_interned_str(s.ident()), ast::CookedStr, suf)
+                (self.id_to_interned_str(ast::Ident::with_empty_ctxt(s)), ast::CookedStr, suf)
             }
             token::Literal(token::StrRaw(s, n), suf) => {
-                (self.id_to_interned_str(s.ident()), ast::RawStr(n), suf)
+                (self.id_to_interned_str(ast::Ident::with_empty_ctxt(s)), ast::RawStr(n), suf)
             }
             _ => return Ok(None)
         };
index a392872f7535b18d089554bfb6ff607fda1793c0..ba24dc3c0a74ec155fbc4d870741374560da667d 100644 (file)
@@ -453,7 +453,7 @@ macro_rules! declare_special_idents_and_keywords {(
             #[allow(non_upper_case_globals)]
             pub const $si_static: ast::Ident = ast::Ident {
                 name: ast::Name($si_name),
-                ctxt: 0,
+                ctxt: ast::EMPTY_CTXT,
             };
          )*
     }
@@ -462,7 +462,7 @@ macro_rules! declare_special_idents_and_keywords {(
         use ast;
         $(
             #[allow(non_upper_case_globals)]
-            pub const $si_static: ast::Name =  ast::Name($si_name);
+            pub const $si_static: ast::Name = ast::Name($si_name);
         )*
     }
 
@@ -729,19 +729,19 @@ pub fn gensym(s: &str) -> ast::Name {
 /// Maps a string to an identifier with an empty syntax context.
 #[inline]
 pub fn str_to_ident(s: &str) -> ast::Ident {
-    ast::Ident::new(intern(s))
+    ast::Ident::with_empty_ctxt(intern(s))
 }
 
 /// Maps a string to a gensym'ed identifier.
 #[inline]
 pub fn gensym_ident(s: &str) -> ast::Ident {
-    ast::Ident::new(gensym(s))
+    ast::Ident::with_empty_ctxt(gensym(s))
 }
 
 // create a fresh name that maps to the same string as the old one.
 // note that this guarantees that str_ptr_eq(ident_to_string(src),interner_get(fresh_name(src)));
 // that is, that the new name and the old one are connected to ptr_eq strings.
-pub fn fresh_name(src: &ast::Ident) -> ast::Name {
+pub fn fresh_name(src: ast::Ident) -> ast::Name {
     let interner = get_ident_interner();
     interner.gensym_copy(src.name)
     // following: debug version. Could work in final except that it's incompatible with
@@ -753,7 +753,7 @@ pub fn fresh_name(src: &ast::Ident) -> ast::Name {
 
 // create a fresh mark.
 pub fn fresh_mark() -> ast::Mrk {
-    gensym("mark").usize() as u32
+    gensym("mark").0
 }
 
 #[cfg(test)]
@@ -763,7 +763,7 @@ mod tests {
     use ext::mtwt;
 
     fn mark_ident(id : ast::Ident, m : ast::Mrk) -> ast::Ident {
-        ast::Ident { name: id.name, ctxt:mtwt::apply_mark(m, id.ctxt) }
+        ast::Ident::new(id.name, mtwt::apply_mark(m, id.ctxt))
     }
 
     #[test] fn mtwt_token_eq_test() {
index 555fdc1ff864759a62e01f9790d08a2d79227d7d..87cecdba28e3d2fed28305a3d635eebe280e5b8d 100644 (file)
@@ -54,8 +54,8 @@ impl PpAnn for NoAnn {}
 
 #[derive(Copy, Clone)]
 pub struct CurrentCommentAndLiteral {
-    cur_cmnt: usize,
-    cur_lit: usize,
+    pub cur_cmnt: usize,
+    pub cur_lit: usize,
 }
 
 pub struct State<'a> {
@@ -297,7 +297,7 @@ pub fn token_to_string(tok: &Token) -> String {
             token::NtBlock(ref e)       => block_to_string(&**e),
             token::NtStmt(ref e)        => stmt_to_string(&**e),
             token::NtPat(ref e)         => pat_to_string(&**e),
-            token::NtIdent(ref e, _)    => ident_to_string(&**e),
+            token::NtIdent(ref e, _)    => ident_to_string(**e),
             token::NtTT(ref e)          => tt_to_string(&**e),
             token::NtArm(ref e)         => arm_to_string(&*e),
             token::NtImplItem(ref e)    => impl_item_to_string(&**e),
@@ -376,8 +376,8 @@ pub fn path_to_string(p: &ast::Path) -> String {
     to_string(|s| s.print_path(p, false, 0))
 }
 
-pub fn ident_to_string(id: &ast::Ident) -> String {
-    to_string(|s| s.print_ident(*id))
+pub fn ident_to_string(id: ast::Ident) -> String {
+    to_string(|s| s.print_ident(id))
 }
 
 pub fn fun_to_string(decl: &ast::FnDecl,
@@ -450,43 +450,368 @@ fn needs_parentheses(expr: &ast::Expr) -> bool {
     }
 }
 
-impl<'a> State<'a> {
-    pub fn ibox(&mut self, u: usize) -> io::Result<()> {
-        self.boxes.push(pp::Breaks::Inconsistent);
-        pp::ibox(&mut self.s, u)
+pub trait PrintState<'a> {
+    fn writer(&mut self) -> &mut pp::Printer<'a>;
+    fn boxes(&mut self) -> &mut Vec<pp::Breaks>;
+    fn comments(&mut self) -> &mut Option<Vec<comments::Comment>>;
+    fn cur_cmnt_and_lit(&mut self) -> &mut CurrentCommentAndLiteral;
+    fn literals(&self) -> &Option<Vec<comments::Literal>>;
+
+    fn word_space(&mut self, w: &str) -> io::Result<()> {
+        try!(word(self.writer(), w));
+        space(self.writer())
     }
 
-    pub fn end(&mut self) -> io::Result<()> {
-        self.boxes.pop().unwrap();
-        pp::end(&mut self.s)
+    fn popen(&mut self) -> io::Result<()> { word(self.writer(), "(") }
+
+    fn pclose(&mut self) -> io::Result<()> { word(self.writer(), ")") }
+
+    fn is_begin(&mut self) -> bool {
+        match self.writer().last_token() {
+            pp::Token::Begin(_) => true,
+            _ => false,
+        }
     }
 
-    pub fn cbox(&mut self, u: usize) -> io::Result<()> {
-        self.boxes.push(pp::Breaks::Consistent);
-        pp::cbox(&mut self.s, u)
+    fn is_end(&mut self) -> bool {
+        match self.writer().last_token() {
+            pp::Token::End => true,
+            _ => false,
+        }
+    }
+
+    // is this the beginning of a line?
+    fn is_bol(&mut self) -> bool {
+        self.writer().last_token().is_eof() || self.writer().last_token().is_hardbreak_tok()
+    }
+
+    fn hardbreak_if_not_bol(&mut self) -> io::Result<()> {
+        if !self.is_bol() {
+            try!(hardbreak(self.writer()))
+        }
+        Ok(())
     }
 
     // "raw box"
-    pub fn rbox(&mut self, u: usize, b: pp::Breaks) -> io::Result<()> {
-        self.boxes.push(b);
-        pp::rbox(&mut self.s, u, b)
+    fn rbox(&mut self, u: usize, b: pp::Breaks) -> io::Result<()> {
+        self.boxes().push(b);
+        pp::rbox(self.writer(), u, b)
     }
 
-    pub fn nbsp(&mut self) -> io::Result<()> { word(&mut self.s, " ") }
+    fn ibox(&mut self, u: usize) -> io::Result<()> {
+        self.boxes().push(pp::Breaks::Inconsistent);
+        pp::ibox(self.writer(), u)
+    }
 
-    pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> {
-        try!(word(&mut self.s, w));
-        self.nbsp()
+    fn end(&mut self) -> io::Result<()> {
+        self.boxes().pop().unwrap();
+        pp::end(self.writer())
     }
 
-    pub fn word_space(&mut self, w: &str) -> io::Result<()> {
-        try!(word(&mut self.s, w));
-        space(&mut self.s)
+    fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], mut op: F) -> io::Result<()>
+        where F: FnMut(&mut Self, &T) -> io::Result<()>,
+    {
+        try!(self.rbox(0, b));
+        let mut first = true;
+        for elt in elts {
+            if first { first = false; } else { try!(self.word_space(",")); }
+            try!(op(self, elt));
+        }
+        self.end()
+    }
+
+    fn next_lit(&mut self, pos: BytePos) -> Option<comments::Literal> {
+        let mut cur_lit = self.cur_cmnt_and_lit().cur_lit;
+
+        let mut result = None;
+
+        if let &Some(ref lits) = self.literals()
+        {
+            while cur_lit < lits.len() {
+                let ltrl = (*lits)[cur_lit].clone();
+                if ltrl.pos > pos { break; }
+                cur_lit += 1;
+                if ltrl.pos == pos {
+                    result = Some(ltrl);
+                    break;
+                }
+            }
+        }
+
+        self.cur_cmnt_and_lit().cur_lit = cur_lit;
+        result
+    }
+
+    fn maybe_print_comment(&mut self, pos: BytePos) -> io::Result<()> {
+        loop {
+            match self.next_comment() {
+                Some(ref cmnt) => {
+                    if (*cmnt).pos < pos {
+                        try!(self.print_comment(cmnt));
+                        self.cur_cmnt_and_lit().cur_cmnt += 1;
+                    } else { break; }
+                }
+                _ => break
+            }
+        }
+        Ok(())
+    }
+
+    fn print_comment(&mut self,
+                     cmnt: &comments::Comment) -> io::Result<()> {
+        match cmnt.style {
+            comments::Mixed => {
+                assert_eq!(cmnt.lines.len(), 1);
+                try!(zerobreak(self.writer()));
+                try!(word(self.writer(), &cmnt.lines[0]));
+                zerobreak(self.writer())
+            }
+            comments::Isolated => {
+                try!(self.hardbreak_if_not_bol());
+                for line in &cmnt.lines {
+                    // Don't print empty lines because they will end up as trailing
+                    // whitespace
+                    if !line.is_empty() {
+                        try!(word(self.writer(), &line[..]));
+                    }
+                    try!(hardbreak(self.writer()));
+                }
+                Ok(())
+            }
+            comments::Trailing => {
+                try!(word(self.writer(), " "));
+                if cmnt.lines.len() == 1 {
+                    try!(word(self.writer(), &cmnt.lines[0]));
+                    hardbreak(self.writer())
+                } else {
+                    try!(self.ibox(0));
+                    for line in &cmnt.lines {
+                        if !line.is_empty() {
+                            try!(word(self.writer(), &line[..]));
+                        }
+                        try!(hardbreak(self.writer()));
+                    }
+                    self.end()
+                }
+            }
+            comments::BlankLine => {
+                // We need to do at least one, possibly two hardbreaks.
+                let is_semi = match self.writer().last_token() {
+                    pp::Token::String(s, _) => ";" == s,
+                    _ => false
+                };
+                if is_semi || self.is_begin() || self.is_end() {
+                    try!(hardbreak(self.writer()));
+                }
+                hardbreak(self.writer())
+            }
+        }
+    }
+
+    fn next_comment(&mut self) -> Option<comments::Comment> {
+        let cur_cmnt = self.cur_cmnt_and_lit().cur_cmnt;
+        match *self.comments() {
+            Some(ref cmnts) => {
+                if cur_cmnt < cmnts.len() {
+                    Some(cmnts[cur_cmnt].clone())
+                } else {
+                    None
+                }
+            }
+            _ => None
+        }
+    }
+
+    fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> {
+        try!(self.maybe_print_comment(lit.span.lo));
+        match self.next_lit(lit.span.lo) {
+            Some(ref ltrl) => {
+                return word(self.writer(), &(*ltrl).lit);
+            }
+            _ => ()
+        }
+        match lit.node {
+            ast::LitStr(ref st, style) => self.print_string(&st, style),
+            ast::LitByte(byte) => {
+                let mut res = String::from("b'");
+                res.extend(ascii::escape_default(byte).map(|c| c as char));
+                res.push('\'');
+                word(self.writer(), &res[..])
+            }
+            ast::LitChar(ch) => {
+                let mut res = String::from("'");
+                res.extend(ch.escape_default());
+                res.push('\'');
+                word(self.writer(), &res[..])
+            }
+            ast::LitInt(i, t) => {
+                match t {
+                    ast::SignedIntLit(st, ast::Plus) => {
+                        word(self.writer(),
+                             &ast_util::int_ty_to_string(st, Some(i as i64)))
+                    }
+                    ast::SignedIntLit(st, ast::Minus) => {
+                        let istr = ast_util::int_ty_to_string(st, Some(-(i as i64)));
+                        word(self.writer(),
+                             &format!("-{}", istr))
+                    }
+                    ast::UnsignedIntLit(ut) => {
+                        word(self.writer(), &ast_util::uint_ty_to_string(ut, Some(i)))
+                    }
+                    ast::UnsuffixedIntLit(ast::Plus) => {
+                        word(self.writer(), &format!("{}", i))
+                    }
+                    ast::UnsuffixedIntLit(ast::Minus) => {
+                        word(self.writer(), &format!("-{}", i))
+                    }
+                }
+            }
+            ast::LitFloat(ref f, t) => {
+                word(self.writer(),
+                     &format!(
+                         "{}{}",
+                         &f,
+                         &ast_util::float_ty_to_string(t)))
+            }
+            ast::LitFloatUnsuffixed(ref f) => word(self.writer(), &f[..]),
+            ast::LitBool(val) => {
+                if val { word(self.writer(), "true") } else { word(self.writer(), "false") }
+            }
+            ast::LitByteStr(ref v) => {
+                let mut escaped: String = String::new();
+                for &ch in v.iter() {
+                    escaped.extend(ascii::escape_default(ch)
+                                         .map(|c| c as char));
+                }
+                word(self.writer(), &format!("b\"{}\"", escaped))
+            }
+        }
+    }
+
+    fn print_string(&mut self, st: &str,
+                    style: ast::StrStyle) -> io::Result<()> {
+        let st = match style {
+            ast::CookedStr => {
+                (format!("\"{}\"", st.escape_default()))
+            }
+            ast::RawStr(n) => {
+                (format!("r{delim}\"{string}\"{delim}",
+                         delim=repeat("#", n),
+                         string=st))
+            }
+        };
+        word(self.writer(), &st[..])
+    }
+
+    fn print_inner_attributes(&mut self,
+                                  attrs: &[ast::Attribute]) -> io::Result<()> {
+        let mut count = 0;
+        for attr in attrs {
+            match attr.node.style {
+                ast::AttrStyle::Inner => {
+                    try!(self.print_attribute(attr));
+                    count += 1;
+                }
+                _ => {/* fallthrough */ }
+            }
+        }
+        if count > 0 {
+            try!(self.hardbreak_if_not_bol());
+        }
+        Ok(())
+    }
+
+    fn print_outer_attributes(&mut self,
+                              attrs: &[ast::Attribute]) -> io::Result<()> {
+        let mut count = 0;
+        for attr in attrs {
+            match attr.node.style {
+                ast::AttrStyle::Outer => {
+                    try!(self.print_attribute(attr));
+                    count += 1;
+                }
+                _ => {/* fallthrough */ }
+            }
+        }
+        if count > 0 {
+            try!(self.hardbreak_if_not_bol());
+        }
+        Ok(())
     }
 
-    pub fn popen(&mut self) -> io::Result<()> { word(&mut self.s, "(") }
+    fn print_attribute(&mut self, attr: &ast::Attribute) -> io::Result<()> {
+        try!(self.hardbreak_if_not_bol());
+        try!(self.maybe_print_comment(attr.span.lo));
+        if attr.node.is_sugared_doc {
+            word(self.writer(), &attr.value_str().unwrap())
+        } else {
+            match attr.node.style {
+                ast::AttrStyle::Inner => try!(word(self.writer(), "#![")),
+                ast::AttrStyle::Outer => try!(word(self.writer(), "#[")),
+            }
+            try!(self.print_meta_item(&*attr.meta()));
+            word(self.writer(), "]")
+        }
+    }
 
-    pub fn pclose(&mut self) -> io::Result<()> { word(&mut self.s, ")") }
+    fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> {
+        try!(self.ibox(indent_unit));
+        match item.node {
+            ast::MetaWord(ref name) => {
+                try!(word(self.writer(), &name));
+            }
+            ast::MetaNameValue(ref name, ref value) => {
+                try!(self.word_space(&name[..]));
+                try!(self.word_space("="));
+                try!(self.print_literal(value));
+            }
+            ast::MetaList(ref name, ref items) => {
+                try!(word(self.writer(), &name));
+                try!(self.popen());
+                try!(self.commasep(Consistent,
+                                   &items[..],
+                                   |s, i| s.print_meta_item(&**i)));
+                try!(self.pclose());
+            }
+        }
+        self.end()
+    }
+}
+
+impl<'a> PrintState<'a> for State<'a> {
+    fn writer(&mut self) -> &mut pp::Printer<'a> {
+        &mut self.s
+    }
+
+    fn boxes(&mut self) -> &mut Vec<pp::Breaks> {
+        &mut self.boxes
+    }
+
+    fn comments(&mut self) -> &mut Option<Vec<comments::Comment>> {
+        &mut self.comments
+    }
+
+    fn cur_cmnt_and_lit(&mut self) -> &mut CurrentCommentAndLiteral {
+        &mut self.cur_cmnt_and_lit
+    }
+
+    fn literals(&self) -> &Option<Vec<comments::Literal>> {
+        &self.literals
+    }
+}
+
+impl<'a> State<'a> {
+    pub fn cbox(&mut self, u: usize) -> io::Result<()> {
+        self.boxes.push(pp::Breaks::Consistent);
+        pp::cbox(&mut self.s, u)
+    }
+
+    pub fn nbsp(&mut self) -> io::Result<()> { word(&mut self.s, " ") }
+
+    pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> {
+        try!(word(&mut self.s, w));
+        self.nbsp()
+    }
 
     pub fn head(&mut self, w: &str) -> io::Result<()> {
         // outer-box is consistent
@@ -523,25 +848,6 @@ impl<'a> State<'a> {
         self.bclose_(span, indent_unit)
     }
 
-    pub fn is_begin(&mut self) -> bool {
-        match self.s.last_token() {
-            pp::Token::Begin(_) => true,
-            _ => false,
-        }
-    }
-
-    pub fn is_end(&mut self) -> bool {
-        match self.s.last_token() {
-            pp::Token::End => true,
-            _ => false,
-        }
-    }
-
-    // is this the beginning of a line?
-    pub fn is_bol(&mut self) -> bool {
-        self.s.last_token().is_eof() || self.s.last_token().is_hardbreak_tok()
-    }
-
     pub fn in_cbox(&self) -> bool {
         match self.boxes.last() {
             Some(&last_box) => last_box == pp::Breaks::Consistent,
@@ -549,12 +855,6 @@ impl<'a> State<'a> {
         }
     }
 
-    pub fn hardbreak_if_not_bol(&mut self) -> io::Result<()> {
-        if !self.is_bol() {
-            try!(hardbreak(&mut self.s))
-        }
-        Ok(())
-    }
     pub fn space_if_not_bol(&mut self) -> io::Result<()> {
         if !self.is_bol() { try!(space(&mut self.s)); }
         Ok(())
@@ -584,17 +884,6 @@ impl<'a> State<'a> {
         word(&mut self.s, "*/")
     }
 
-    pub fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], mut op: F) -> io::Result<()> where
-        F: FnMut(&mut State, &T) -> io::Result<()>,
-    {
-        try!(self.rbox(0, b));
-        let mut first = true;
-        for elt in elts {
-            if first { first = false; } else { try!(self.word_space(",")); }
-            try!(op(self, elt));
-        }
-        self.end()
-    }
 
 
     pub fn commasep_cmnt<T, F, G>(&mut self,
@@ -933,7 +1222,7 @@ impl<'a> State<'a> {
             }
             ast::ItemStruct(ref struct_def, ref generics) => {
                 try!(self.head(&visibility_qualified(item.vis,"struct")));
-                try!(self.print_struct(&**struct_def, generics, item.ident, item.span));
+                try!(self.print_struct(&struct_def, generics, item.ident, item.span, true));
             }
 
             ast::ItemDefaultImpl(unsafety, ref trait_ref) => {
@@ -1017,16 +1306,14 @@ impl<'a> State<'a> {
                 }
                 try!(self.bclose(item.span));
             }
-            // I think it's reasonable to hide the context here:
-            ast::ItemMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
-                                            ..}) => {
+            ast::ItemMac(codemap::Spanned { ref node, .. }) => {
                 try!(self.print_visibility(item.vis));
-                try!(self.print_path(pth, false, 0));
+                try!(self.print_path(&node.path, false, 0));
                 try!(word(&mut self.s, "! "));
                 try!(self.print_ident(item.ident));
                 try!(self.cbox(indent_unit));
                 try!(self.popen());
-                try!(self.print_tts(&tts[..]));
+                try!(self.print_tts(&node.tts[..]));
                 try!(self.pclose());
                 try!(word(&mut self.s, ";"));
                 try!(self.end());
@@ -1097,17 +1384,18 @@ impl<'a> State<'a> {
     }
 
     pub fn print_struct(&mut self,
-                        struct_def: &ast::StructDef,
+                        struct_def: &ast::VariantData,
                         generics: &ast::Generics,
                         ident: ast::Ident,
-                        span: codemap::Span) -> io::Result<()> {
+                        span: codemap::Span,
+                        print_finalizer: bool) -> io::Result<()> {
         try!(self.print_ident(ident));
         try!(self.print_generics(generics));
-        if ast_util::struct_def_is_tuple_like(struct_def) {
-            if !struct_def.fields.is_empty() {
+        if !struct_def.is_struct() {
+            if struct_def.is_tuple() {
                 try!(self.popen());
                 try!(self.commasep(
-                    Inconsistent, &struct_def.fields,
+                    Inconsistent, struct_def.fields(),
                     |s, field| {
                         match field.node.kind {
                             ast::NamedField(..) => panic!("unexpected named field"),
@@ -1122,7 +1410,9 @@ impl<'a> State<'a> {
                 try!(self.pclose());
             }
             try!(self.print_where_clause(&generics.where_clause));
-            try!(word(&mut self.s, ";"));
+            if print_finalizer {
+                try!(word(&mut self.s, ";"));
+            }
             try!(self.end());
             self.end() // close the outer-box
         } else {
@@ -1131,7 +1421,7 @@ impl<'a> State<'a> {
             try!(self.bopen());
             try!(self.hardbreak_if_not_bol());
 
-            for field in &struct_def.fields {
+            for field in struct_def.fields() {
                 match field.node.kind {
                     ast::UnnamedField(..) => panic!("unexpected unnamed field"),
                     ast::NamedField(ident, visibility) => {
@@ -1217,24 +1507,9 @@ impl<'a> State<'a> {
     }
 
     pub fn print_variant(&mut self, v: &ast::Variant) -> io::Result<()> {
-        try!(self.print_visibility(v.node.vis));
-        match v.node.kind {
-            ast::TupleVariantKind(ref args) => {
-                try!(self.print_ident(v.node.name));
-                if !args.is_empty() {
-                    try!(self.popen());
-                    try!(self.commasep(Consistent,
-                                       &args[..],
-                                       |s, arg| s.print_type(&*arg.ty)));
-                    try!(self.pclose());
-                }
-            }
-            ast::StructVariantKind(ref struct_def) => {
-                try!(self.head(""));
-                let generics = ast_util::empty_generics();
-                try!(self.print_struct(&**struct_def, &generics, v.node.name, v.span));
-            }
-        }
+        try!(self.head(""));
+        let generics = ast_util::empty_generics();
+        try!(self.print_struct(&v.node.data, &generics, v.node.name, v.span, false));
         match v.node.disr_expr {
             Some(ref d) => {
                 try!(space(&mut self.s));
@@ -1310,14 +1585,13 @@ impl<'a> State<'a> {
             ast::TypeImplItem(ref ty) => {
                 try!(self.print_associated_type(ii.ident, None, Some(ty)));
             }
-            ast::MacImplItem(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
-                                                ..}) => {
+            ast::MacImplItem(codemap::Spanned { ref node, .. }) => {
                 // code copied from ItemMac:
-                try!(self.print_path(pth, false, 0));
+                try!(self.print_path(&node.path, false, 0));
                 try!(word(&mut self.s, "! "));
                 try!(self.cbox(indent_unit));
                 try!(self.popen());
-                try!(self.print_tts(&tts[..]));
+                try!(self.print_tts(&node.tts[..]));
                 try!(self.pclose());
                 try!(word(&mut self.s, ";"));
                 try!(self.end())
@@ -1326,58 +1600,6 @@ impl<'a> State<'a> {
         self.ann.post(self, NodeSubItem(ii.id))
     }
 
-    pub fn print_outer_attributes(&mut self,
-                                  attrs: &[ast::Attribute]) -> io::Result<()> {
-        let mut count = 0;
-        for attr in attrs {
-            match attr.node.style {
-                ast::AttrOuter => {
-                    try!(self.print_attribute(attr));
-                    count += 1;
-                }
-                _ => {/* fallthrough */ }
-            }
-        }
-        if count > 0 {
-            try!(self.hardbreak_if_not_bol());
-        }
-        Ok(())
-    }
-
-    pub fn print_inner_attributes(&mut self,
-                                  attrs: &[ast::Attribute]) -> io::Result<()> {
-        let mut count = 0;
-        for attr in attrs {
-            match attr.node.style {
-                ast::AttrInner => {
-                    try!(self.print_attribute(attr));
-                    count += 1;
-                }
-                _ => {/* fallthrough */ }
-            }
-        }
-        if count > 0 {
-            try!(self.hardbreak_if_not_bol());
-        }
-        Ok(())
-    }
-
-    pub fn print_attribute(&mut self, attr: &ast::Attribute) -> io::Result<()> {
-        try!(self.hardbreak_if_not_bol());
-        try!(self.maybe_print_comment(attr.span.lo));
-        if attr.node.is_sugared_doc {
-            word(&mut self.s, &attr.value_str().unwrap())
-        } else {
-            match attr.node.style {
-                ast::AttrInner => try!(word(&mut self.s, "#![")),
-                ast::AttrOuter => try!(word(&mut self.s, "#[")),
-            }
-            try!(self.print_meta_item(&*attr.meta()));
-            word(&mut self.s, "]")
-        }
-    }
-
-
     pub fn print_stmt(&mut self, st: &ast::Stmt) -> io::Result<()> {
         try!(self.maybe_print_comment(st.span.lo));
         match st.node {
@@ -1437,8 +1659,8 @@ impl<'a> State<'a> {
                                       attrs: &[ast::Attribute],
                                       close_box: bool) -> io::Result<()> {
         match blk.rules {
-            ast::UnsafeBlock(..) | ast::PushUnsafeBlock(..) => try!(self.word_space("unsafe")),
-            ast::DefaultBlock    | ast::PopUnsafeBlock(..) => ()
+            ast::UnsafeBlock(..) => try!(self.word_space("unsafe")),
+            ast::DefaultBlock => ()
         }
         try!(self.maybe_print_comment(blk.span.lo));
         try!(self.ann.pre(self, NodeBlock(blk)));
@@ -1528,23 +1750,18 @@ impl<'a> State<'a> {
 
     pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken)
                      -> io::Result<()> {
-        match m.node {
-            // I think it's reasonable to hide the ctxt here:
-            ast::MacInvocTT(ref pth, ref tts, _) => {
-                try!(self.print_path(pth, false, 0));
-                try!(word(&mut self.s, "!"));
-                match delim {
-                    token::Paren => try!(self.popen()),
-                    token::Bracket => try!(word(&mut self.s, "[")),
-                    token::Brace => try!(self.bopen()),
-                }
-                try!(self.print_tts(tts));
-                match delim {
-                    token::Paren => self.pclose(),
-                    token::Bracket => word(&mut self.s, "]"),
-                    token::Brace => self.bclose(m.span),
-                }
-            }
+        try!(self.print_path(&m.node.path, false, 0));
+        try!(word(&mut self.s, "!"));
+        match delim {
+            token::Paren => try!(self.popen()),
+            token::Bracket => try!(word(&mut self.s, "[")),
+            token::Brace => try!(self.bopen()),
+        }
+        try!(self.print_tts(&m.node.tts));
+        match delim {
+            token::Paren => self.pclose(),
+            token::Bracket => word(&mut self.s, "]"),
+            token::Brace => self.bclose(m.span),
         }
     }
 
@@ -1582,13 +1799,12 @@ impl<'a> State<'a> {
         Ok(())
     }
 
-    fn print_expr_box(&mut self,
-                      place: &Option<P<ast::Expr>>,
-                      expr: &ast::Expr) -> io::Result<()> {
-        try!(word(&mut self.s, "box"));
-        try!(word(&mut self.s, "("));
-        try!(place.as_ref().map_or(Ok(()), |e|self.print_expr(&**e)));
-        try!(self.word_space(")"));
+    fn print_expr_in_place(&mut self,
+                           place: &ast::Expr,
+                           expr: &ast::Expr) -> io::Result<()> {
+        try!(self.word_space("in"));
+        try!(self.print_expr(place));
+        try!(space(&mut self.s));
         self.print_expr(expr)
     }
 
@@ -1617,34 +1833,34 @@ impl<'a> State<'a> {
                          fields: &[ast::Field],
                          wth: &Option<P<ast::Expr>>) -> io::Result<()> {
         try!(self.print_path(path, true, 0));
-        if !(fields.is_empty() && wth.is_none()) {
-            try!(word(&mut self.s, "{"));
-            try!(self.commasep_cmnt(
-                Consistent,
-                &fields[..],
-                |s, field| {
-                    try!(s.ibox(indent_unit));
-                    try!(s.print_ident(field.ident.node));
-                    try!(s.word_space(":"));
-                    try!(s.print_expr(&*field.expr));
-                    s.end()
-                },
-                |f| f.span));
-            match *wth {
-                Some(ref expr) => {
-                    try!(self.ibox(indent_unit));
-                    if !fields.is_empty() {
-                        try!(word(&mut self.s, ","));
-                        try!(space(&mut self.s));
-                    }
-                    try!(word(&mut self.s, ".."));
-                    try!(self.print_expr(&**expr));
-                    try!(self.end());
+        try!(word(&mut self.s, "{"));
+        try!(self.commasep_cmnt(
+            Consistent,
+            &fields[..],
+            |s, field| {
+                try!(s.ibox(indent_unit));
+                try!(s.print_ident(field.ident.node));
+                try!(s.word_space(":"));
+                try!(s.print_expr(&*field.expr));
+                s.end()
+            },
+            |f| f.span));
+        match *wth {
+            Some(ref expr) => {
+                try!(self.ibox(indent_unit));
+                if !fields.is_empty() {
+                    try!(word(&mut self.s, ","));
+                    try!(space(&mut self.s));
                 }
-                _ => try!(word(&mut self.s, ",")),
+                try!(word(&mut self.s, ".."));
+                try!(self.print_expr(&**expr));
+                try!(self.end());
+            }
+            _ => if !fields.is_empty() {
+                try!(word(&mut self.s, ","))
             }
-            try!(word(&mut self.s, "}"));
         }
+        try!(word(&mut self.s, "}"));
         Ok(())
     }
 
@@ -1719,8 +1935,12 @@ impl<'a> State<'a> {
         try!(self.ibox(indent_unit));
         try!(self.ann.pre(self, NodeExpr(expr)));
         match expr.node {
-            ast::ExprBox(ref place, ref expr) => {
-                try!(self.print_expr_box(place, &**expr));
+            ast::ExprBox(ref expr) => {
+                try!(self.word_space("box"));
+                try!(self.print_expr(expr));
+            }
+            ast::ExprInPlace(ref place, ref expr) => {
+                try!(self.print_expr_in_place(place, expr));
             }
             ast::ExprVec(ref exprs) => {
                 try!(self.print_expr_vec(&exprs[..]));
@@ -1813,7 +2033,7 @@ impl<'a> State<'a> {
                 try!(space(&mut self.s));
                 try!(self.print_block(&**blk));
             }
-            ast::ExprMatch(ref expr, ref arms, _) => {
+            ast::ExprMatch(ref expr, ref arms) => {
                 try!(self.cbox(indent_unit));
                 try!(self.ibox(4));
                 try!(self.word_nbsp("match"));
@@ -1980,7 +2200,7 @@ impl<'a> State<'a> {
                 if a.alignstack {
                     options.push("alignstack");
                 }
-                if a.dialect == ast::AsmDialect::AsmIntel {
+                if a.dialect == ast::AsmDialect::Intel {
                     options.push("intel");
                 }
 
@@ -2620,35 +2840,11 @@ impl<'a> State<'a> {
         Ok(())
     }
 
-    pub fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> {
-        try!(self.ibox(indent_unit));
-        match item.node {
-            ast::MetaWord(ref name) => {
-                try!(word(&mut self.s, &name));
-            }
-            ast::MetaNameValue(ref name, ref value) => {
-                try!(self.word_space(&name[..]));
-                try!(self.word_space("="));
-                try!(self.print_literal(value));
-            }
-            ast::MetaList(ref name, ref items) => {
-                try!(word(&mut self.s, &name));
-                try!(self.popen());
-                try!(self.commasep(Consistent,
-                                   &items[..],
-                                   |s, i| s.print_meta_item(&**i)));
-                try!(self.pclose());
-            }
-        }
-        self.end()
-    }
-
     pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> io::Result<()> {
         match vp.node {
             ast::ViewPathSimple(ident, ref path) => {
                 try!(self.print_path(path, false, 0));
 
-                // FIXME(#6993) can't compare identifiers directly here
                 if path.segments.last().unwrap().identifier.name !=
                         ident.name {
                     try!(space(&mut self.s));
@@ -2832,181 +3028,6 @@ impl<'a> State<'a> {
         Ok(())
     }
 
-    pub fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> {
-        try!(self.maybe_print_comment(lit.span.lo));
-        match self.next_lit(lit.span.lo) {
-            Some(ref ltrl) => {
-                return word(&mut self.s, &(*ltrl).lit);
-            }
-            _ => ()
-        }
-        match lit.node {
-            ast::LitStr(ref st, style) => self.print_string(&st, style),
-            ast::LitByte(byte) => {
-                let mut res = String::from("b'");
-                res.extend(ascii::escape_default(byte).map(|c| c as char));
-                res.push('\'');
-                word(&mut self.s, &res[..])
-            }
-            ast::LitChar(ch) => {
-                let mut res = String::from("'");
-                res.extend(ch.escape_default());
-                res.push('\'');
-                word(&mut self.s, &res[..])
-            }
-            ast::LitInt(i, t) => {
-                match t {
-                    ast::SignedIntLit(st, ast::Plus) => {
-                        word(&mut self.s,
-                             &ast_util::int_ty_to_string(st, Some(i as i64)))
-                    }
-                    ast::SignedIntLit(st, ast::Minus) => {
-                        let istr = ast_util::int_ty_to_string(st, Some(-(i as i64)));
-                        word(&mut self.s,
-                             &format!("-{}", istr))
-                    }
-                    ast::UnsignedIntLit(ut) => {
-                        word(&mut self.s, &ast_util::uint_ty_to_string(ut, Some(i)))
-                    }
-                    ast::UnsuffixedIntLit(ast::Plus) => {
-                        word(&mut self.s, &format!("{}", i))
-                    }
-                    ast::UnsuffixedIntLit(ast::Minus) => {
-                        word(&mut self.s, &format!("-{}", i))
-                    }
-                }
-            }
-            ast::LitFloat(ref f, t) => {
-                word(&mut self.s,
-                     &format!(
-                         "{}{}",
-                         &f,
-                         &ast_util::float_ty_to_string(t)))
-            }
-            ast::LitFloatUnsuffixed(ref f) => word(&mut self.s, &f[..]),
-            ast::LitBool(val) => {
-                if val { word(&mut self.s, "true") } else { word(&mut self.s, "false") }
-            }
-            ast::LitByteStr(ref v) => {
-                let mut escaped: String = String::new();
-                for &ch in v.iter() {
-                    escaped.extend(ascii::escape_default(ch)
-                                         .map(|c| c as char));
-                }
-                word(&mut self.s, &format!("b\"{}\"", escaped))
-            }
-        }
-    }
-
-    pub fn next_lit(&mut self, pos: BytePos) -> Option<comments::Literal> {
-        match self.literals {
-            Some(ref lits) => {
-                while self.cur_cmnt_and_lit.cur_lit < lits.len() {
-                    let ltrl = (*lits)[self.cur_cmnt_and_lit.cur_lit].clone();
-                    if ltrl.pos > pos { return None; }
-                    self.cur_cmnt_and_lit.cur_lit += 1;
-                    if ltrl.pos == pos { return Some(ltrl); }
-                }
-                None
-            }
-            _ => None
-        }
-    }
-
-    pub fn maybe_print_comment(&mut self, pos: BytePos) -> io::Result<()> {
-        loop {
-            match self.next_comment() {
-                Some(ref cmnt) => {
-                    if (*cmnt).pos < pos {
-                        try!(self.print_comment(cmnt));
-                        self.cur_cmnt_and_lit.cur_cmnt += 1;
-                    } else { break; }
-                }
-                _ => break
-            }
-        }
-        Ok(())
-    }
-
-    pub fn print_comment(&mut self,
-                         cmnt: &comments::Comment) -> io::Result<()> {
-        match cmnt.style {
-            comments::Mixed => {
-                assert_eq!(cmnt.lines.len(), 1);
-                try!(zerobreak(&mut self.s));
-                try!(word(&mut self.s, &cmnt.lines[0]));
-                zerobreak(&mut self.s)
-            }
-            comments::Isolated => {
-                try!(self.hardbreak_if_not_bol());
-                for line in &cmnt.lines {
-                    // Don't print empty lines because they will end up as trailing
-                    // whitespace
-                    if !line.is_empty() {
-                        try!(word(&mut self.s, &line[..]));
-                    }
-                    try!(hardbreak(&mut self.s));
-                }
-                Ok(())
-            }
-            comments::Trailing => {
-                try!(word(&mut self.s, " "));
-                if cmnt.lines.len() == 1 {
-                    try!(word(&mut self.s, &cmnt.lines[0]));
-                    hardbreak(&mut self.s)
-                } else {
-                    try!(self.ibox(0));
-                    for line in &cmnt.lines {
-                        if !line.is_empty() {
-                            try!(word(&mut self.s, &line[..]));
-                        }
-                        try!(hardbreak(&mut self.s));
-                    }
-                    self.end()
-                }
-            }
-            comments::BlankLine => {
-                // We need to do at least one, possibly two hardbreaks.
-                let is_semi = match self.s.last_token() {
-                    pp::Token::String(s, _) => ";" == s,
-                    _ => false
-                };
-                if is_semi || self.is_begin() || self.is_end() {
-                    try!(hardbreak(&mut self.s));
-                }
-                hardbreak(&mut self.s)
-            }
-        }
-    }
-
-    pub fn print_string(&mut self, st: &str,
-                        style: ast::StrStyle) -> io::Result<()> {
-        let st = match style {
-            ast::CookedStr => {
-                (format!("\"{}\"", st.escape_default()))
-            }
-            ast::RawStr(n) => {
-                (format!("r{delim}\"{string}\"{delim}",
-                         delim=repeat("#", n),
-                         string=st))
-            }
-        };
-        word(&mut self.s, &st[..])
-    }
-
-    pub fn next_comment(&mut self) -> Option<comments::Comment> {
-        match self.comments {
-            Some(ref cmnts) => {
-                if self.cur_cmnt_and_lit.cur_cmnt < cmnts.len() {
-                    Some(cmnts[self.cur_cmnt_and_lit.cur_cmnt].clone())
-                } else {
-                    None
-                }
-            }
-            _ => None
-        }
-    }
-
     pub fn print_opt_abi_and_extern_if_nondefault(&mut self,
                                                   opt_abi: Option<abi::Abi>)
         -> io::Result<()> {
@@ -3037,13 +3058,14 @@ impl<'a> State<'a> {
                                 abi: abi::Abi,
                                 vis: ast::Visibility) -> io::Result<()> {
         try!(word(&mut self.s, &visibility_qualified(vis, "")));
-        try!(self.print_unsafety(unsafety));
 
         match constness {
             ast::Constness::NotConst => {}
             ast::Constness::Const => try!(self.word_nbsp("const"))
         }
 
+        try!(self.print_unsafety(unsafety));
+
         if abi != abi::Rust {
             try!(self.word_nbsp("extern"));
             try!(self.word_nbsp(&abi.to_string()));
@@ -3096,14 +3118,12 @@ mod tests {
             name: ident,
             attrs: Vec::new(),
             // making this up as I go.... ?
-            kind: ast::TupleVariantKind(Vec::new()),
-            id: 0,
+            data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
             disr_expr: None,
-            vis: ast::Public,
         });
 
         let varstr = variant_to_string(&var);
-        assert_eq!(varstr, "pub principal_skinner");
+        assert_eq!(varstr, "principal_skinner");
     }
 
     #[test]
index d6974abd394f9bdaa9788b8c83b4912e26b51a60..345adff23443a943b86d5aacf11cd1f87f244470 100644 (file)
@@ -154,7 +154,7 @@ impl fold::Folder for PreludeInjector {
                 span: self.span,
                 node: ast::Attribute_ {
                     id: attr::mk_attr_id(),
-                    style: ast::AttrOuter,
+                    style: ast::AttrStyle::Outer,
                     value: P(ast::MetaItem {
                         span: self.span,
                         node: ast::MetaWord(special_idents::prelude_import.name.as_str()),
index 7ae9e4646e516b32bee9972485f904b3f974d2d6..6e9c161293de27359ef5fb91e3a79ff1f93242e2 100644 (file)
@@ -69,7 +69,7 @@ impl<T: Eq + Hash + Clone + 'static> Interner<T> {
 
     pub fn get(&self, idx: Name) -> T {
         let vect = self.vect.borrow();
-        (*vect)[idx.usize()].clone()
+        (*vect)[idx.0 as usize].clone()
     }
 
     pub fn len(&self) -> usize {
@@ -196,13 +196,13 @@ impl StrInterner {
         let new_idx = Name(self.len() as u32);
         // leave out of map to avoid colliding
         let mut vect = self.vect.borrow_mut();
-        let existing = (*vect)[idx.usize()].clone();
+        let existing = (*vect)[idx.0 as usize].clone();
         vect.push(existing);
         new_idx
     }
 
     pub fn get(&self, idx: Name) -> RcStr {
-        (*self.vect.borrow())[idx.usize()].clone()
+        (*self.vect.borrow())[idx.0 as usize].clone()
     }
 
     pub fn len(&self) -> usize {
index 5353d12b67813fe483dee91c92409ab2da067a5b..d65e37fd2abc141295905b94946819e78012561f 100644 (file)
@@ -65,7 +65,6 @@ impl<T> SmallVector<T> {
                 result
             }
             One(ref v) => {
-                // FIXME: Could be replaced with `slice::ref_slice(v)` when it is stable.
                 unsafe { slice::from_raw_parts(v, 1) }
             }
             Many(ref vs) => vs
@@ -129,7 +128,7 @@ impl<T> SmallVector<T> {
     }
 
     /// Deprecated: use `into_iter`.
-    #[unstable(feature = "rustc_private")]
+    #[unstable(feature = "rustc_private", issue = "0")]
     #[deprecated(since = "1.0.0", reason = "use into_iter")]
     pub fn move_iter(self) -> IntoIter<T> {
         self.into_iter()
index 8365a7375c68dbed3911b4d036db1f2665a52dd7..1614d7d4517f26a3f8409538ef0a89411db02884 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
 
 use abi::Abi;
 use ast::*;
-use ast;
 use codemap::Span;
-use ptr::P;
-use owned_slice::OwnedSlice;
 
 #[derive(Copy, Clone, PartialEq, Eq)]
 pub enum FnKind<'a> {
@@ -56,7 +53,7 @@ pub trait Visitor<'v> : Sized {
         // Nothing to do.
     }
     fn visit_ident(&mut self, span: Span, ident: Ident) {
-        self.visit_name(span, ident.name);
+        walk_ident(self, span, ident);
     }
     fn visit_mod(&mut self, m: &'v Mod, _s: Span, _n: NodeId) { walk_mod(self, m) }
     fn visit_foreign_item(&mut self, i: &'v ForeignItem) { walk_foreign_item(self, i) }
@@ -83,32 +80,20 @@ pub trait Visitor<'v> : Sized {
     fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: &'v TraitBoundModifier) {
         walk_poly_trait_ref(self, t, m)
     }
-    fn visit_struct_def(&mut self, s: &'v StructDef, _: Ident, _: &'v Generics, _: NodeId) {
+    fn visit_variant_data(&mut self, s: &'v VariantData, _: Ident,
+                        _: &'v Generics, _: NodeId, _: Span) {
         walk_struct_def(self, s)
     }
     fn visit_struct_field(&mut self, s: &'v StructField) { walk_struct_field(self, s) }
     fn visit_enum_def(&mut self, enum_definition: &'v EnumDef,
-                      generics: &'v Generics) {
-        walk_enum_def(self, enum_definition, generics)
+                      generics: &'v Generics, item_id: NodeId, _: Span) {
+        walk_enum_def(self, enum_definition, generics, item_id)
     }
-
-    fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics) { walk_variant(self, v, g) }
-
-    /// Visits an optional reference to a lifetime. The `span` is the span of some surrounding
-    /// reference should opt_lifetime be None.
-    fn visit_opt_lifetime_ref(&mut self,
-                              _span: Span,
-                              opt_lifetime: &'v Option<Lifetime>) {
-        match *opt_lifetime {
-            Some(ref l) => self.visit_lifetime_ref(l),
-            None => ()
-        }
-    }
-    fn visit_lifetime_bound(&mut self, lifetime: &'v Lifetime) {
-        walk_lifetime_bound(self, lifetime)
+    fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics, item_id: NodeId) {
+        walk_variant(self, v, g, item_id)
     }
-    fn visit_lifetime_ref(&mut self, lifetime: &'v Lifetime) {
-        walk_lifetime_ref(self, lifetime)
+    fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
+        walk_lifetime(self, lifetime)
     }
     fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) {
         walk_lifetime_def(self, lifetime)
@@ -124,9 +109,12 @@ pub trait Visitor<'v> : Sized {
         // definition in your trait impl:
         // visit::walk_mac(self, _mac)
     }
-    fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) {
+    fn visit_path(&mut self, path: &'v Path, _id: NodeId) {
         walk_path(self, path)
     }
+    fn visit_path_list_item(&mut self, prefix: &'v Path, item: &'v PathListItem) {
+        walk_path_list_item(self, prefix, item)
+    }
     fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
         walk_path_segment(self, path_span, path_segment)
     }
@@ -137,53 +125,88 @@ pub trait Visitor<'v> : Sized {
         walk_assoc_type_binding(self, type_binding)
     }
     fn visit_attribute(&mut self, _attr: &'v Attribute) {}
+    fn visit_macro_def(&mut self, macro_def: &'v MacroDef) {
+        walk_macro_def(self, macro_def)
+    }
 }
 
-pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
-    visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
-    for attr in &krate.attrs {
-        visitor.visit_attribute(attr);
+#[macro_export]
+macro_rules! walk_list {
+    ($visitor: expr, $method: ident, $list: expr) => {
+        for elem in $list {
+            $visitor.$method(elem)
+        }
+    };
+    ($visitor: expr, $method: ident, $list: expr, $($extra_args: expr),*) => {
+        for elem in $list {
+            $visitor.$method(elem, $($extra_args,)*)
+        }
     }
 }
 
-pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod) {
-    for item in &module.items {
-        visitor.visit_item(&**item)
+pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option<Name>) {
+    for name in opt_name {
+        visitor.visit_name(span, name);
     }
 }
 
-pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
-    visitor.visit_pat(&*local.pat);
-    walk_ty_opt(visitor, &local.ty);
-    walk_expr_opt(visitor, &local.init);
+pub fn walk_opt_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_ident: Option<Ident>) {
+    for ident in opt_ident {
+        visitor.visit_ident(span, ident);
+    }
 }
 
-pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V,
-                                              lifetime_def: &'v LifetimeDef) {
-    visitor.visit_name(lifetime_def.lifetime.span, lifetime_def.lifetime.name);
-    for bound in &lifetime_def.bounds {
-        visitor.visit_lifetime_bound(bound);
-    }
+pub fn walk_ident<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, ident: Ident) {
+    visitor.visit_name(span, ident.name);
+}
+
+pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate) {
+    visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
+    walk_list!(visitor, visit_attribute, &krate.attrs);
+    walk_list!(visitor, visit_macro_def, &krate.exported_macros);
+}
+
+pub fn walk_macro_def<'v, V: Visitor<'v>>(visitor: &mut V, macro_def: &'v MacroDef) {
+    visitor.visit_ident(macro_def.span, macro_def.ident);
+    walk_opt_ident(visitor, macro_def.span, macro_def.imported_from);
+    walk_list!(visitor, visit_attribute, &macro_def.attrs);
 }
 
-pub fn walk_lifetime_bound<'v, V: Visitor<'v>>(visitor: &mut V,
-                                               lifetime_ref: &'v Lifetime) {
-    visitor.visit_lifetime_ref(lifetime_ref)
+pub fn walk_mod<'v, V: Visitor<'v>>(visitor: &mut V, module: &'v Mod) {
+    walk_list!(visitor, visit_item, &module.items);
 }
 
-pub fn walk_lifetime_ref<'v, V: Visitor<'v>>(visitor: &mut V,
-                                             lifetime_ref: &'v Lifetime) {
-    visitor.visit_name(lifetime_ref.span, lifetime_ref.name)
+pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
+    visitor.visit_pat(&local.pat);
+    walk_list!(visitor, visit_ty, &local.ty);
+    walk_list!(visitor, visit_expr, &local.init);
+}
+
+pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) {
+    visitor.visit_name(lifetime.span, lifetime.name);
+}
+
+pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V,
+                                              lifetime_def: &'v LifetimeDef) {
+    visitor.visit_lifetime(&lifetime_def.lifetime);
+    walk_list!(visitor, visit_lifetime, &lifetime_def.bounds);
 }
 
 pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V,
                                               explicit_self: &'v ExplicitSelf) {
     match explicit_self.node {
-        SelfStatic | SelfValue(_) => {},
-        SelfRegion(ref lifetime, _, _) => {
-            visitor.visit_opt_lifetime_ref(explicit_self.span, lifetime)
+        SelfStatic => {},
+        SelfValue(ident) => {
+            visitor.visit_ident(explicit_self.span, ident)
+        }
+        SelfRegion(ref opt_lifetime, _, ident) => {
+            visitor.visit_ident(explicit_self.span, ident);
+            walk_list!(visitor, visit_lifetime, opt_lifetime);
+        }
+        SelfExplicit(ref typ, ident) => {
+            visitor.visit_ident(explicit_self.span, ident);
+            visitor.visit_ty(typ)
         }
-        SelfExplicit(ref typ, _) => visitor.visit_ty(&**typ),
     }
 }
 
@@ -192,7 +215,7 @@ pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V,
                                   _modifier: &'v TraitBoundModifier)
     where V: Visitor<'v>
 {
-    walk_lifetime_decls_helper(visitor, &trait_ref.bound_lifetimes);
+    walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes);
     visitor.visit_trait_ref(&trait_ref.trait_ref);
 }
 
@@ -206,7 +229,9 @@ pub fn walk_trait_ref<'v,V>(visitor: &mut V,
 pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
     visitor.visit_ident(item.span, item.ident);
     match item.node {
-        ItemExternCrate(..) => {}
+        ItemExternCrate(opt_name) => {
+            walk_opt_name(visitor, item.span, opt_name)
+        }
         ItemUse(ref vp) => {
             match vp.node {
                 ViewPathSimple(ident, ref path) => {
@@ -217,38 +242,26 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
                     visitor.visit_path(path, item.id);
                 }
                 ViewPathList(ref prefix, ref list) => {
-                    for id in list {
-                        match id.node {
-                            PathListIdent { name, rename, .. } => {
-                                visitor.visit_ident(id.span, name);
-                                if let Some(ident) = rename {
-                                    visitor.visit_ident(id.span, ident);
-                                }
-                            }
-                            PathListMod { rename, .. } => {
-                                if let Some(ident) = rename {
-                                    visitor.visit_ident(id.span, ident);
-                                }
-                            }
+                    if !list.is_empty() {
+                        for item in list {
+                            visitor.visit_path_list_item(prefix, item)
                         }
+                    } else {
+                        visitor.visit_path(prefix, item.id);
                     }
-
-                    // Note that the `prefix` here is not a complete
-                    // path, so we don't use `visit_path`.
-                    walk_path(visitor, prefix);
                 }
             }
         }
         ItemStatic(ref typ, _, ref expr) |
         ItemConst(ref typ, ref expr) => {
-            visitor.visit_ty(&**typ);
-            visitor.visit_expr(&**expr);
+            visitor.visit_ty(typ);
+            visitor.visit_expr(expr);
         }
         ItemFn(ref declaration, unsafety, constness, abi, ref generics, ref body) => {
             visitor.visit_fn(FnKind::ItemFn(item.ident, generics, unsafety,
                                             constness, abi, item.vis),
-                             &**declaration,
-                             &**body,
+                             declaration,
+                             body,
                              item.span,
                              item.id)
         }
@@ -256,126 +269,80 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_mod(module, item.span, item.id)
         }
         ItemForeignMod(ref foreign_module) => {
-            for foreign_item in &foreign_module.items {
-                visitor.visit_foreign_item(&**foreign_item)
-            }
+            walk_list!(visitor, visit_foreign_item, &foreign_module.items);
         }
         ItemTy(ref typ, ref type_parameters) => {
-            visitor.visit_ty(&**typ);
+            visitor.visit_ty(typ);
             visitor.visit_generics(type_parameters)
         }
         ItemEnum(ref enum_definition, ref type_parameters) => {
             visitor.visit_generics(type_parameters);
-            visitor.visit_enum_def(enum_definition, type_parameters)
+            visitor.visit_enum_def(enum_definition, type_parameters, item.id, item.span)
         }
         ItemDefaultImpl(_, ref trait_ref) => {
             visitor.visit_trait_ref(trait_ref)
         }
         ItemImpl(_, _,
                  ref type_parameters,
-                 ref trait_reference,
+                 ref opt_trait_reference,
                  ref typ,
                  ref impl_items) => {
             visitor.visit_generics(type_parameters);
-            match *trait_reference {
-                Some(ref trait_reference) => visitor.visit_trait_ref(trait_reference),
-                None => ()
-            }
-            visitor.visit_ty(&**typ);
-            for impl_item in impl_items {
-                visitor.visit_impl_item(impl_item);
-            }
+            walk_list!(visitor, visit_trait_ref, opt_trait_reference);
+            visitor.visit_ty(typ);
+            walk_list!(visitor, visit_impl_item, impl_items);
         }
         ItemStruct(ref struct_definition, ref generics) => {
             visitor.visit_generics(generics);
-            visitor.visit_struct_def(&**struct_definition,
-                                     item.ident,
-                                     generics,
-                                     item.id)
+            visitor.visit_variant_data(struct_definition, item.ident,
+                                     generics, item.id, item.span);
         }
         ItemTrait(_, ref generics, ref bounds, ref methods) => {
             visitor.visit_generics(generics);
-            walk_ty_param_bounds_helper(visitor, bounds);
-            for method in methods {
-                visitor.visit_trait_item(method)
-            }
+            walk_list!(visitor, visit_ty_param_bound, bounds);
+            walk_list!(visitor, visit_trait_item, methods);
         }
         ItemMac(ref mac) => visitor.visit_mac(mac),
     }
-    for attr in &item.attrs {
-        visitor.visit_attribute(attr);
-    }
+    walk_list!(visitor, visit_attribute, &item.attrs);
 }
 
 pub fn walk_enum_def<'v, V: Visitor<'v>>(visitor: &mut V,
                                          enum_definition: &'v EnumDef,
-                                         generics: &'v Generics) {
-    for variant in &enum_definition.variants {
-        visitor.visit_variant(&**variant, generics);
-    }
+                                         generics: &'v Generics,
+                                         item_id: NodeId) {
+    walk_list!(visitor, visit_variant, &enum_definition.variants, generics, item_id);
 }
 
 pub fn walk_variant<'v, V: Visitor<'v>>(visitor: &mut V,
                                         variant: &'v Variant,
-                                        generics: &'v Generics) {
+                                        generics: &'v Generics,
+                                        item_id: NodeId) {
     visitor.visit_ident(variant.span, variant.node.name);
-
-    match variant.node.kind {
-        TupleVariantKind(ref variant_arguments) => {
-            for variant_argument in variant_arguments {
-                visitor.visit_ty(&*variant_argument.ty)
-            }
-        }
-        StructVariantKind(ref struct_definition) => {
-            visitor.visit_struct_def(&**struct_definition,
-                                     variant.node.name,
-                                     generics,
-                                     variant.node.id)
-        }
-    }
-    match variant.node.disr_expr {
-        Some(ref expr) => visitor.visit_expr(&**expr),
-        None => ()
-    }
-    for attr in &variant.node.attrs {
-        visitor.visit_attribute(attr);
-    }
-}
-
-pub fn skip_ty<'v, V: Visitor<'v>>(_: &mut V, _: &'v Ty) {
-    // Empty!
-}
-
-pub fn walk_ty_opt<'v, V: Visitor<'v>>(visitor: &mut V, optional_type: &'v Option<P<Ty>>) {
-    match *optional_type {
-        Some(ref ty) => visitor.visit_ty(&**ty),
-        None => ()
-    }
+    visitor.visit_variant_data(&variant.node.data, variant.node.name,
+                             generics, item_id, variant.span);
+    walk_list!(visitor, visit_expr, &variant.node.disr_expr);
+    walk_list!(visitor, visit_attribute, &variant.node.attrs);
 }
 
 pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
     match typ.node {
         TyVec(ref ty) | TyParen(ref ty) => {
-            visitor.visit_ty(&**ty)
+            visitor.visit_ty(ty)
         }
         TyPtr(ref mutable_type) => {
-            visitor.visit_ty(&*mutable_type.ty)
+            visitor.visit_ty(&mutable_type.ty)
         }
-        TyRptr(ref lifetime, ref mutable_type) => {
-            visitor.visit_opt_lifetime_ref(typ.span, lifetime);
-            visitor.visit_ty(&*mutable_type.ty)
+        TyRptr(ref opt_lifetime, ref mutable_type) => {
+            walk_list!(visitor, visit_lifetime, opt_lifetime);
+            visitor.visit_ty(&mutable_type.ty)
         }
         TyTup(ref tuple_element_types) => {
-            for tuple_element_type in tuple_element_types {
-                visitor.visit_ty(&**tuple_element_type)
-            }
+            walk_list!(visitor, visit_ty, tuple_element_types);
         }
         TyBareFn(ref function_declaration) => {
-            for argument in &function_declaration.decl.inputs {
-                visitor.visit_ty(&*argument.ty)
-            }
-            walk_fn_ret_ty(visitor, &function_declaration.decl.output);
-            walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
+            walk_fn_decl(visitor, &function_declaration.decl);
+            walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes);
         }
         TyPath(ref maybe_qself, ref path) => {
             if let Some(ref qself) = *maybe_qself {
@@ -384,18 +351,18 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             visitor.visit_path(path, typ.id);
         }
         TyObjectSum(ref ty, ref bounds) => {
-            visitor.visit_ty(&**ty);
-            walk_ty_param_bounds_helper(visitor, bounds);
+            visitor.visit_ty(ty);
+            walk_list!(visitor, visit_ty_param_bound, bounds);
         }
         TyFixedLengthVec(ref ty, ref expression) => {
-            visitor.visit_ty(&**ty);
-            visitor.visit_expr(&**expression)
+            visitor.visit_ty(ty);
+            visitor.visit_expr(expression)
         }
         TyPolyTraitRef(ref bounds) => {
-            walk_ty_param_bounds_helper(visitor, bounds)
+            walk_list!(visitor, visit_ty_param_bound, bounds);
         }
         TyTypeof(ref expression) => {
-            visitor.visit_expr(&**expression)
+            visitor.visit_expr(expression)
         }
         TyInfer => {}
         TyMac(ref mac) => {
@@ -404,19 +371,22 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
     }
 }
 
-pub fn walk_lifetime_decls_helper<'v, V: Visitor<'v>>(visitor: &mut V,
-                                                      lifetimes: &'v Vec<LifetimeDef>) {
-    for l in lifetimes {
-        visitor.visit_lifetime_def(l);
-    }
-}
-
 pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
     for segment in &path.segments {
         visitor.visit_path_segment(path.span, segment);
     }
 }
 
+pub fn walk_path_list_item<'v, V: Visitor<'v>>(visitor: &mut V, prefix: &'v Path,
+                                               item: &'v PathListItem) {
+    for segment in &prefix.segments {
+        visitor.visit_path_segment(prefix.span, segment);
+    }
+
+    walk_opt_ident(visitor, item.span, item.node.name());
+    walk_opt_ident(visitor, item.span, item.node.rename());
+}
+
 pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
                                              path_span: Span,
                                              segment: &'v PathSegment) {
@@ -428,24 +398,14 @@ pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
                                                 _path_span: Span,
                                                 path_parameters: &'v PathParameters) {
     match *path_parameters {
-        ast::AngleBracketedParameters(ref data) => {
-            for typ in data.types.iter() {
-                visitor.visit_ty(&**typ);
-            }
-            for lifetime in &data.lifetimes {
-                visitor.visit_lifetime_ref(lifetime);
-            }
-            for binding in data.bindings.iter() {
-                visitor.visit_assoc_type_binding(&**binding);
-            }
+        AngleBracketedParameters(ref data) => {
+            walk_list!(visitor, visit_ty, &data.types);
+            walk_list!(visitor, visit_lifetime, &data.lifetimes);
+            walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
         }
-        ast::ParenthesizedParameters(ref data) => {
-            for typ in &data.inputs {
-                visitor.visit_ty(&**typ);
-            }
-            if let Some(ref typ) = data.output {
-                visitor.visit_ty(&**typ);
-            }
+        ParenthesizedParameters(ref data) => {
+            walk_list!(visitor, visit_ty, &data.inputs);
+            walk_list!(visitor, visit_ty, &data.output);
         }
     }
 }
@@ -453,17 +413,15 @@ pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
 pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
                                                    type_binding: &'v TypeBinding) {
     visitor.visit_ident(type_binding.span, type_binding.ident);
-    visitor.visit_ty(&*type_binding.ty);
+    visitor.visit_ty(&type_binding.ty);
 }
 
 pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
     match pattern.node {
-        PatEnum(ref path, ref children) => {
+        PatEnum(ref path, ref opt_children) => {
             visitor.visit_path(path, pattern.id);
-            if let Some(ref children) = *children {
-                for child in children {
-                    visitor.visit_pat(&*child)
-                }
+            if let Some(ref children) = *opt_children {
+                walk_list!(visitor, visit_pat, children);
             }
         }
         PatQPath(ref qself, ref path) => {
@@ -473,41 +431,31 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
         PatStruct(ref path, ref fields, _) => {
             visitor.visit_path(path, pattern.id);
             for field in fields {
-                visitor.visit_pat(&*field.node.pat)
+                visitor.visit_ident(field.span, field.node.ident);
+                visitor.visit_pat(&field.node.pat)
             }
         }
         PatTup(ref tuple_elements) => {
-            for tuple_element in tuple_elements {
-                visitor.visit_pat(&**tuple_element)
-            }
+            walk_list!(visitor, visit_pat, tuple_elements);
         }
         PatBox(ref subpattern) |
         PatRegion(ref subpattern, _) => {
-            visitor.visit_pat(&**subpattern)
+            visitor.visit_pat(subpattern)
         }
         PatIdent(_, ref pth1, ref optional_subpattern) => {
             visitor.visit_ident(pth1.span, pth1.node);
-            match *optional_subpattern {
-                None => {}
-                Some(ref subpattern) => visitor.visit_pat(&**subpattern),
-            }
+            walk_list!(visitor, visit_pat, optional_subpattern);
         }
-        PatLit(ref expression) => visitor.visit_expr(&**expression),
+        PatLit(ref expression) => visitor.visit_expr(expression),
         PatRange(ref lower_bound, ref upper_bound) => {
-            visitor.visit_expr(&**lower_bound);
-            visitor.visit_expr(&**upper_bound)
+            visitor.visit_expr(lower_bound);
+            visitor.visit_expr(upper_bound)
         }
         PatWild(_) => (),
-        PatVec(ref prepattern, ref slice_pattern, ref postpatterns) => {
-            for prepattern in prepattern {
-                visitor.visit_pat(&**prepattern)
-            }
-            if let Some(ref slice_pattern) = *slice_pattern {
-                visitor.visit_pat(&**slice_pattern)
-            }
-            for postpattern in postpatterns {
-                visitor.visit_pat(&**postpattern)
-            }
+        PatVec(ref prepatterns, ref slice_pattern, ref postpatterns) => {
+            walk_list!(visitor, visit_pat, prepatterns);
+            walk_list!(visitor, visit_pat, slice_pattern);
+            walk_list!(visitor, visit_pat, postpatterns);
         }
         PatMac(ref mac) => visitor.visit_mac(mac),
     }
@@ -519,22 +467,13 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V,
 
     match foreign_item.node {
         ForeignItemFn(ref function_declaration, ref generics) => {
-            walk_fn_decl(visitor, &**function_declaration);
+            walk_fn_decl(visitor, function_declaration);
             visitor.visit_generics(generics)
         }
-        ForeignItemStatic(ref typ, _) => visitor.visit_ty(&**typ),
-    }
-
-    for attr in &foreign_item.attrs {
-        visitor.visit_attribute(attr);
+        ForeignItemStatic(ref typ, _) => visitor.visit_ty(typ),
     }
-}
 
-pub fn walk_ty_param_bounds_helper<'v, V: Visitor<'v>>(visitor: &mut V,
-                                                       bounds: &'v OwnedSlice<TyParamBound>) {
-    for bound in bounds.iter() {
-        visitor.visit_ty_param_bound(bound)
-    }
+    walk_list!(visitor, visit_attribute, &foreign_item.attrs);
 }
 
 pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V,
@@ -544,41 +483,40 @@ pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V,
             visitor.visit_poly_trait_ref(typ, modifier);
         }
         RegionTyParamBound(ref lifetime) => {
-            visitor.visit_lifetime_bound(lifetime);
+            visitor.visit_lifetime(lifetime);
         }
     }
 }
 
 pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) {
-    for param in generics.ty_params.iter() {
+    for param in &generics.ty_params {
         visitor.visit_ident(param.span, param.ident);
-        walk_ty_param_bounds_helper(visitor, &param.bounds);
-        walk_ty_opt(visitor, &param.default);
+        walk_list!(visitor, visit_ty_param_bound, &param.bounds);
+        walk_list!(visitor, visit_ty, &param.default);
     }
-    walk_lifetime_decls_helper(visitor, &generics.lifetimes);
+    walk_list!(visitor, visit_lifetime_def, &generics.lifetimes);
     for predicate in &generics.where_clause.predicates {
         match predicate {
-            &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bounded_ty,
+            &WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty,
                                                                           ref bounds,
+                                                                          ref bound_lifetimes,
                                                                           ..}) => {
-                visitor.visit_ty(&**bounded_ty);
-                walk_ty_param_bounds_helper(visitor, bounds);
+                visitor.visit_ty(bounded_ty);
+                walk_list!(visitor, visit_ty_param_bound, bounds);
+                walk_list!(visitor, visit_lifetime_def, bound_lifetimes);
             }
-            &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
+            &WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime,
                                                                             ref bounds,
                                                                             ..}) => {
-                visitor.visit_lifetime_ref(lifetime);
-
-                for bound in bounds {
-                    visitor.visit_lifetime_ref(bound);
-                }
+                visitor.visit_lifetime(lifetime);
+                walk_list!(visitor, visit_lifetime, bounds);
             }
-            &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id,
+            &WherePredicate::EqPredicate(WhereEqPredicate{id,
                                                                     ref path,
                                                                     ref ty,
                                                                     ..}) => {
                 visitor.visit_path(path, id);
-                visitor.visit_ty(&**ty);
+                visitor.visit_ty(ty);
             }
         }
     }
@@ -586,25 +524,20 @@ pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics
 
 pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionRetTy) {
     if let Return(ref output_ty) = *ret_ty {
-        visitor.visit_ty(&**output_ty)
+        visitor.visit_ty(output_ty)
     }
 }
 
 pub fn walk_fn_decl<'v, V: Visitor<'v>>(visitor: &mut V, function_declaration: &'v FnDecl) {
     for argument in &function_declaration.inputs {
-        visitor.visit_pat(&*argument.pat);
-        visitor.visit_ty(&*argument.ty)
+        visitor.visit_pat(&argument.pat);
+        visitor.visit_ty(&argument.ty)
     }
     walk_fn_ret_ty(visitor, &function_declaration.output)
 }
 
-pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
-                                   function_kind: FnKind<'v>,
-                                   function_declaration: &'v FnDecl,
-                                   function_body: &'v Block,
-                                   _span: Span) {
-    walk_fn_decl(visitor, function_declaration);
-
+pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V,
+                                        function_kind: FnKind<'v>) {
     match function_kind {
         FnKind::ItemFn(_, generics, _, _, _, _) => {
             visitor.visit_generics(generics);
@@ -613,23 +546,27 @@ pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
             visitor.visit_generics(&sig.generics);
             visitor.visit_explicit_self(&sig.explicit_self);
         }
-        FnKind::Closure(..) => {}
+        FnKind::Closure => {}
     }
+}
 
+pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V,
+                                   function_kind: FnKind<'v>,
+                                   function_declaration: &'v FnDecl,
+                                   function_body: &'v Block,
+                                   _span: Span) {
+    walk_fn_decl(visitor, function_declaration);
+    walk_fn_kind(visitor, function_kind);
     visitor.visit_block(function_body)
 }
 
 pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) {
     visitor.visit_ident(trait_item.span, trait_item.ident);
-    for attr in &trait_item.attrs {
-        visitor.visit_attribute(attr);
-    }
+    walk_list!(visitor, visit_attribute, &trait_item.attrs);
     match trait_item.node {
         ConstTraitItem(ref ty, ref default) => {
             visitor.visit_ty(ty);
-            if let Some(ref expr) = *default {
-                visitor.visit_expr(expr);
-            }
+            walk_list!(visitor, visit_expr, default);
         }
         MethodTraitItem(ref sig, None) => {
             visitor.visit_explicit_self(&sig.explicit_self);
@@ -641,17 +578,15 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
                              body, trait_item.span, trait_item.id);
         }
         TypeTraitItem(ref bounds, ref default) => {
-            walk_ty_param_bounds_helper(visitor, bounds);
-            walk_ty_opt(visitor, default);
+            walk_list!(visitor, visit_ty_param_bound, bounds);
+            walk_list!(visitor, visit_ty, default);
         }
     }
 }
 
 pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
     visitor.visit_ident(impl_item.span, impl_item.ident);
-    for attr in &impl_item.attrs {
-        visitor.visit_attribute(attr);
-    }
+    walk_list!(visitor, visit_attribute, &impl_item.attrs);
     match impl_item.node {
         ConstImplItem(ref ty, ref expr) => {
             visitor.visit_ty(ty);
@@ -671,60 +606,36 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
 }
 
 pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V,
-                                           struct_definition: &'v StructDef) {
-    for field in &struct_definition.fields {
-        visitor.visit_struct_field(field)
-    }
+                                           struct_definition: &'v VariantData) {
+    walk_list!(visitor, visit_struct_field, struct_definition.fields());
 }
 
 pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V,
                                              struct_field: &'v StructField) {
-    if let NamedField(name, _) = struct_field.node.kind {
-        visitor.visit_ident(struct_field.span, name);
-    }
-
-    visitor.visit_ty(&*struct_field.node.ty);
-
-    for attr in &struct_field.node.attrs {
-        visitor.visit_attribute(attr);
-    }
+    walk_opt_ident(visitor, struct_field.span, struct_field.node.ident());
+    visitor.visit_ty(&struct_field.node.ty);
+    walk_list!(visitor, visit_attribute, &struct_field.node.attrs);
 }
 
 pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block) {
-    for statement in &block.stmts {
-        visitor.visit_stmt(&**statement)
-    }
-    walk_expr_opt(visitor, &block.expr)
+    walk_list!(visitor, visit_stmt, &block.stmts);
+    walk_list!(visitor, visit_expr, &block.expr);
 }
 
 pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) {
     match statement.node {
-        StmtDecl(ref declaration, _) => visitor.visit_decl(&**declaration),
+        StmtDecl(ref declaration, _) => visitor.visit_decl(declaration),
         StmtExpr(ref expression, _) | StmtSemi(ref expression, _) => {
-            visitor.visit_expr(&**expression)
+            visitor.visit_expr(expression)
         }
-        StmtMac(ref mac, _) => visitor.visit_mac(&**mac),
+        StmtMac(ref mac, _) => visitor.visit_mac(mac),
     }
 }
 
 pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) {
     match declaration.node {
-        DeclLocal(ref local) => visitor.visit_local(&**local),
-        DeclItem(ref item) => visitor.visit_item(&**item),
-    }
-}
-
-pub fn walk_expr_opt<'v, V: Visitor<'v>>(visitor: &mut V,
-                                         optional_expression: &'v Option<P<Expr>>) {
-    match *optional_expression {
-        None => {}
-        Some(ref expression) => visitor.visit_expr(&**expression),
-    }
-}
-
-pub fn walk_exprs<'v, V: Visitor<'v>>(visitor: &mut V, expressions: &'v [P<Expr>]) {
-    for expression in expressions {
-        visitor.visit_expr(&**expression)
+        DeclLocal(ref local) => visitor.visit_local(local),
+        DeclItem(ref item) => visitor.visit_item(item),
     }
 }
 
@@ -734,114 +645,118 @@ pub fn walk_mac<'v, V: Visitor<'v>>(_: &mut V, _: &'v Mac) {
 
 pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
     match expression.node {
-        ExprBox(ref place, ref subexpression) => {
-            place.as_ref().map(|e|visitor.visit_expr(&**e));
-            visitor.visit_expr(&**subexpression)
+        ExprBox(ref subexpression) => {
+            visitor.visit_expr(subexpression)
+        }
+        ExprInPlace(ref place, ref subexpression) => {
+            visitor.visit_expr(place);
+            visitor.visit_expr(subexpression)
         }
         ExprVec(ref subexpressions) => {
-            walk_exprs(visitor, subexpressions)
+            walk_list!(visitor, visit_expr, subexpressions);
         }
         ExprRepeat(ref element, ref count) => {
-            visitor.visit_expr(&**element);
-            visitor.visit_expr(&**count)
+            visitor.visit_expr(element);
+            visitor.visit_expr(count)
         }
         ExprStruct(ref path, ref fields, ref optional_base) => {
             visitor.visit_path(path, expression.id);
             for field in fields {
-                visitor.visit_expr(&*field.expr)
+                visitor.visit_ident(field.ident.span, field.ident.node);
+                visitor.visit_expr(&field.expr)
             }
-            walk_expr_opt(visitor, optional_base)
+            walk_list!(visitor, visit_expr, optional_base);
         }
         ExprTup(ref subexpressions) => {
-            for subexpression in subexpressions {
-                visitor.visit_expr(&**subexpression)
-            }
+            walk_list!(visitor, visit_expr, subexpressions);
         }
         ExprCall(ref callee_expression, ref arguments) => {
-            for argument in arguments {
-                visitor.visit_expr(&**argument)
-            }
-            visitor.visit_expr(&**callee_expression)
+            walk_list!(visitor, visit_expr, arguments);
+            visitor.visit_expr(callee_expression)
         }
-        ExprMethodCall(_, ref types, ref arguments) => {
-            walk_exprs(visitor, arguments);
-            for typ in types {
-                visitor.visit_ty(&**typ)
-            }
+        ExprMethodCall(ref ident, ref types, ref arguments) => {
+            visitor.visit_ident(ident.span, ident.node);
+            walk_list!(visitor, visit_expr, arguments);
+            walk_list!(visitor, visit_ty, types);
         }
         ExprBinary(_, ref left_expression, ref right_expression) => {
-            visitor.visit_expr(&**left_expression);
-            visitor.visit_expr(&**right_expression)
+            visitor.visit_expr(left_expression);
+            visitor.visit_expr(right_expression)
         }
         ExprAddrOf(_, ref subexpression) | ExprUnary(_, ref subexpression) => {
-            visitor.visit_expr(&**subexpression)
+            visitor.visit_expr(subexpression)
         }
         ExprLit(_) => {}
         ExprCast(ref subexpression, ref typ) => {
-            visitor.visit_expr(&**subexpression);
-            visitor.visit_ty(&**typ)
+            visitor.visit_expr(subexpression);
+            visitor.visit_ty(typ)
         }
         ExprIf(ref head_expression, ref if_block, ref optional_else) => {
-            visitor.visit_expr(&**head_expression);
-            visitor.visit_block(&**if_block);
-            walk_expr_opt(visitor, optional_else)
+            visitor.visit_expr(head_expression);
+            visitor.visit_block(if_block);
+            walk_list!(visitor, visit_expr, optional_else);
         }
-        ExprWhile(ref subexpression, ref block, _) => {
-            visitor.visit_expr(&**subexpression);
-            visitor.visit_block(&**block)
+        ExprWhile(ref subexpression, ref block, opt_ident) => {
+            visitor.visit_expr(subexpression);
+            visitor.visit_block(block);
+            walk_opt_ident(visitor, expression.span, opt_ident)
         }
         ExprIfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => {
-            visitor.visit_pat(&**pattern);
-            visitor.visit_expr(&**subexpression);
-            visitor.visit_block(&**if_block);
-            walk_expr_opt(visitor, optional_else);
-        }
-        ExprWhileLet(ref pattern, ref subexpression, ref block, _) => {
-            visitor.visit_pat(&**pattern);
-            visitor.visit_expr(&**subexpression);
-            visitor.visit_block(&**block);
-        }
-        ExprForLoop(ref pattern, ref subexpression, ref block, _) => {
-            visitor.visit_pat(&**pattern);
-            visitor.visit_expr(&**subexpression);
-            visitor.visit_block(&**block)
-        }
-        ExprLoop(ref block, _) => visitor.visit_block(&**block),
-        ExprMatch(ref subexpression, ref arms, _) => {
-            visitor.visit_expr(&**subexpression);
-            for arm in arms {
-                visitor.visit_arm(arm)
-            }
+            visitor.visit_pat(pattern);
+            visitor.visit_expr(subexpression);
+            visitor.visit_block(if_block);
+            walk_list!(visitor, visit_expr, optional_else);
+        }
+        ExprWhileLet(ref pattern, ref subexpression, ref block, opt_ident) => {
+            visitor.visit_pat(pattern);
+            visitor.visit_expr(subexpression);
+            visitor.visit_block(block);
+            walk_opt_ident(visitor, expression.span, opt_ident)
+        }
+        ExprForLoop(ref pattern, ref subexpression, ref block, opt_ident) => {
+            visitor.visit_pat(pattern);
+            visitor.visit_expr(subexpression);
+            visitor.visit_block(block);
+            walk_opt_ident(visitor, expression.span, opt_ident)
+        }
+        ExprLoop(ref block, opt_ident) => {
+            visitor.visit_block(block);
+            walk_opt_ident(visitor, expression.span, opt_ident)
+        }
+        ExprMatch(ref subexpression, ref arms) => {
+            visitor.visit_expr(subexpression);
+            walk_list!(visitor, visit_arm, arms);
         }
         ExprClosure(_, ref function_declaration, ref body) => {
             visitor.visit_fn(FnKind::Closure,
-                             &**function_declaration,
-                             &**body,
+                             function_declaration,
+                             body,
                              expression.span,
                              expression.id)
         }
-        ExprBlock(ref block) => visitor.visit_block(&**block),
+        ExprBlock(ref block) => visitor.visit_block(block),
         ExprAssign(ref left_hand_expression, ref right_hand_expression) => {
-            visitor.visit_expr(&**right_hand_expression);
-            visitor.visit_expr(&**left_hand_expression)
+            visitor.visit_expr(right_hand_expression);
+            visitor.visit_expr(left_hand_expression)
         }
         ExprAssignOp(_, ref left_expression, ref right_expression) => {
-            visitor.visit_expr(&**right_expression);
-            visitor.visit_expr(&**left_expression)
+            visitor.visit_expr(right_expression);
+            visitor.visit_expr(left_expression)
         }
-        ExprField(ref subexpression, _) => {
-            visitor.visit_expr(&**subexpression);
+        ExprField(ref subexpression, ref ident) => {
+            visitor.visit_expr(subexpression);
+            visitor.visit_ident(ident.span, ident.node);
         }
         ExprTupField(ref subexpression, _) => {
-            visitor.visit_expr(&**subexpression);
+            visitor.visit_expr(subexpression);
         }
         ExprIndex(ref main_expression, ref index_expression) => {
-            visitor.visit_expr(&**main_expression);
-            visitor.visit_expr(&**index_expression)
+            visitor.visit_expr(main_expression);
+            visitor.visit_expr(index_expression)
         }
         ExprRange(ref start, ref end) => {
-            walk_expr_opt(visitor, start);
-            walk_expr_opt(visitor, end)
+            walk_list!(visitor, visit_expr, start);
+            walk_list!(visitor, visit_expr, end);
         }
         ExprPath(ref maybe_qself, ref path) => {
             if let Some(ref qself) = *maybe_qself {
@@ -849,22 +764,24 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             }
             visitor.visit_path(path, expression.id)
         }
-        ExprBreak(_) | ExprAgain(_) => {}
+        ExprBreak(ref opt_sp_ident) | ExprAgain(ref opt_sp_ident) => {
+            for sp_ident in opt_sp_ident {
+                visitor.visit_ident(sp_ident.span, sp_ident.node);
+            }
+        }
         ExprRet(ref optional_expression) => {
-            walk_expr_opt(visitor, optional_expression)
+            walk_list!(visitor, visit_expr, optional_expression);
         }
         ExprMac(ref mac) => visitor.visit_mac(mac),
         ExprParen(ref subexpression) => {
-            visitor.visit_expr(&**subexpression)
+            visitor.visit_expr(subexpression)
         }
         ExprInlineAsm(ref ia) => {
-            for input in &ia.inputs {
-                let (_, ref input) = *input;
-                visitor.visit_expr(&**input)
+            for &(_, ref input) in &ia.inputs {
+                visitor.visit_expr(&input)
             }
-            for output in &ia.outputs {
-                let (_, ref output, _) = *output;
-                visitor.visit_expr(&**output)
+            for &(_, ref output, _) in &ia.outputs {
+                visitor.visit_expr(&output)
             }
         }
     }
@@ -873,12 +790,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
 }
 
 pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
-    for pattern in &arm.pats {
-        visitor.visit_pat(&**pattern)
-    }
-    walk_expr_opt(visitor, &arm.guard);
-    visitor.visit_expr(&*arm.body);
-    for attr in &arm.attrs {
-        visitor.visit_attribute(attr);
-    }
+    walk_list!(visitor, visit_pat, &arm.pats);
+    walk_list!(visitor, visit_expr, &arm.guard);
+    visitor.visit_expr(&arm.body);
+    walk_list!(visitor, visit_attribute, &arm.attrs);
 }
index 8bf8044f814315b00e4acc4c5ef07a9d1ef051d1..ced3a7d47d7b674a84d38babf317d6ed74e09edd 100644 (file)
@@ -57,7 +57,6 @@
 #![deny(missing_docs)]
 
 #![feature(box_syntax)]
-#![feature(path_ext)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #![feature(str_char)]
index 16062060df087d90d5d349b48c0761b7ceadb3e6..0e05ac53bc8780536cfec774d30d74a3269ef963 100644 (file)
@@ -102,7 +102,7 @@ fn test_get_dbpath_for_term() {
     fn x(t: &str) -> String {
         let p = get_dbpath_for_term(t).expect("no terminfo entry found");
         p.to_str().unwrap().to_string()
-    };
+    }
     assert!(x("screen") == "/usr/share/terminfo/s/screen");
     assert!(get_dbpath_for_term("") == None);
     env::set_var("TERMINFO_DIRS", ":");
index ad00bb667330861aef91c614e43fbcb84b095fef..cfe75779536a293cd890cdfc8458f616134a5d67 100644 (file)
@@ -924,7 +924,7 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA
             } else {
                 None
             }
-        };
+        }
         filtered.into_iter().filter_map(filter).collect()
     };
 
index c0e52795e9a0d7dbb627ed6d5675a0b2b8f5e89b..175471a35a2f6e9ed2b997c22d19f19307f33367 100644 (file)
@@ -443,7 +443,7 @@ main(int argc, char **argv)
        if (data.show_time) {
                double elapsed;
 
-               if (t1 == -1 || t2 == -1) {
+               if (t1 == ((clock_t) -1) || t2 == ((clock_t) -1)) {
                        fprintf(stderr, "Failed to get the time.\n");
                        return 1;
                }
index 3831b3c36f27cfbe697e57c15d6bca87b0344018..e2731dab41a2dd627c25f80bba5e6c51b7595225 100644 (file)
@@ -549,7 +549,7 @@ find_emph_char(uint8_t *data, size_t size, uint8_t c)
                        }
 
                        /* not a well-formed codespan; use found matching emph char */
-                       if (i >= size) return tmp_i;
+                       if (bt < span_nb && i >= size) return tmp_i;
                }
                /* skipping a link */
                else if (data[i] == '[') {
index 71b0e6a5ae80497a9ca09a1521416869af936cc3..d3247b681d5585cfcf9c2f8c40fdc906e213f01e 100644 (file)
@@ -12,10 +12,10 @@ extern "C" {
  * CONSTANTS *
  *************/
 
-#define HOEDOWN_VERSION "3.0.4"
+#define HOEDOWN_VERSION "3.0.5"
 #define HOEDOWN_VERSION_MAJOR 3
 #define HOEDOWN_VERSION_MINOR 0
-#define HOEDOWN_VERSION_REVISION 4
+#define HOEDOWN_VERSION_REVISION 5
 
 
 /*************
index 8824cef2a816c153ea468796cebea190d99a91f6..f7895d694c8246923e15c57a8839c0811ff62ff6 100644 (file)
@@ -218,3 +218,7 @@ uint64_t get_y(struct S s) {
 uint64_t get_z(struct S s) {
     return s.z;
 }
+
+uint64_t get_c_many_params(void *a, void *b, void *c, void *d, struct quad f) {
+    return f.c;
+}
index aca0db4e1adbefad9bb35145f8eaad1043042cbd..4b6d67d2d2620a68490a237eb3d700b0f0cfc1e0 100644 (file)
@@ -23,8 +23,6 @@ use error::{err, CliResult, CommandResult};
 use book;
 use book::{Book, BookItem};
 
-use javascript;
-
 use rustdoc;
 
 struct Build;
@@ -82,7 +80,7 @@ fn write_toc(book: &Book, current_page: &BookItem, out: &mut Write) -> io::Resul
 }
 
 fn render(book: &Book, tgt: &Path) -> CliResult<()> {
-    let tmp = try!(TempDir::new("rust-book"));
+    let tmp = try!(TempDir::new("rustbook"));
 
     for (_section, item) in book.iter() {
         let out_path = match item.path.parent() {
@@ -113,26 +111,28 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> {
         // write the prelude to a temporary HTML file for rustdoc inclusion
         let prelude = tmp.path().join("prelude.html");
         {
-            let mut toc = BufWriter::new(try!(File::create(&prelude)));
-            try!(writeln!(&mut toc, r#"<div id="nav">
-                <button id="toggle-nav">
-                  <span class="sr-only">Toggle navigation</span>
-                  <span class="bar"></span>
-                  <span class="bar"></span>
-                  <span class="bar"></span>
-                </button>
-              </div>"#));
-            let _ = write_toc(book, &item, &mut toc);
-            try!(writeln!(&mut toc, "<div id='page-wrapper'>"));
-            try!(writeln!(&mut toc, "<div id='page'>"));
+            let mut buffer = BufWriter::new(try!(File::create(&prelude)));
+            try!(writeln!(&mut buffer, r#"
+                <div id="nav">
+                    <button id="toggle-nav">
+                        <span class="sr-only">Toggle navigation</span>
+                        <span class="bar"></span>
+                        <span class="bar"></span>
+                        <span class="bar"></span>
+                    </button>
+                </div>"#));
+            let _ = write_toc(book, &item, &mut buffer);
+            try!(writeln!(&mut buffer, "<div id='page-wrapper'>"));
+            try!(writeln!(&mut buffer, "<div id='page'>"));
         }
 
         // write the postlude to a temporary HTML file for rustdoc inclusion
         let postlude = tmp.path().join("postlude.html");
         {
-            let mut toc = BufWriter::new(try!(File::create(&postlude)));
-            try!(toc.write_all(javascript::JAVASCRIPT.as_bytes()));
-            try!(writeln!(&mut toc, "</div></div>"));
+            let mut buffer = BufWriter::new(try!(File::create(&postlude)));
+            try!(writeln!(&mut buffer, "<script src='rustbook.js'></script>"));
+            try!(writeln!(&mut buffer, "<script src='playpen.js'></script>"));
+            try!(writeln!(&mut buffer, "</div></div>"));
         }
 
         try!(fs::create_dir_all(&out_path));
@@ -144,7 +144,7 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> {
             format!("--html-before-content={}", prelude.display()),
             format!("--html-after-content={}", postlude.display()),
             format!("--markdown-playground-url=https://play.rust-lang.org"),
-            format!("--markdown-css={}", item.path_to_root.join("rust-book.css").display()),
+            format!("--markdown-css={}", item.path_to_root.join("rustbook.css").display()),
             "--markdown-no-toc".to_string(),
         ];
         let output_result = rustdoc::main_args(rustdoc_args);
@@ -199,10 +199,10 @@ impl Subcommand for Build {
         let css = include_bytes!("static/rustbook.css");
         let js = include_bytes!("static/rustbook.js");
 
-        let mut css_file = try!(File::create(tgt.join("rust-book.css")));
+        let mut css_file = try!(File::create(tgt.join("rustbook.css")));
         try!(css_file.write_all(css));
 
-        let mut js_file = try!(File::create(tgt.join("rust-book.js")));
+        let mut js_file = try!(File::create(tgt.join("rustbook.js")));
         try!(js_file.write_all(js));
 
 
index 995d2f2494a490b1845344aaa86886152a733bd9..c90c2b936092a4b643483d20b26d37851139d929 100644 (file)
@@ -36,7 +36,7 @@ impl Subcommand for Help {
 }
 
 pub fn usage() {
-    println!("Usage: rust-book <command> [<args>]");
+    println!("Usage: rustbook <command> [<args>]");
     println!("");
     println!("The <command> must be one of:");
     println!("  help    Print this message.");
diff --git a/src/rustbook/javascript.rs b/src/rustbook/javascript.rs
deleted file mode 100644 (file)
index beddc23..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// The rust-book JavaScript in string form.
-
-pub static JAVASCRIPT: &'static str = r#"
-<script type="text/javascript" src="rust-book.js"></script>
-<script type="text/javascript" src="playpen.js"></script>
-"#;
index 81f8c8c40fdff7a23c220e54f320793aaae327d4..d23e868eeadd192fc649763d79810881f10164d0 100644 (file)
@@ -35,11 +35,8 @@ mod build;
 mod serve;
 mod test;
 
-mod javascript;
-
 static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT;
 
-#[cfg(not(test))] // thanks #12327
 fn main() {
     let mut term = Term::new();
     let cmd: Vec<_> = env::args().collect();
index 6b9e7aa58f247ce9122ed5ff897a1407957a6f30..ba0151fa2ed4773116c06a94773cdb844806331b 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+ * Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
  * file at the top-level directory of this distribution and at
  * http://rust-lang.org/COPYRIGHT.
  *
  * except according to those terms.
  */
 
-@import url("../rust.css");
+@import url('../rust.css');
 
 body {
-    max-width:none;
-    font: 16px/1.4 'Source Serif Pro', Georgia, Times, 'Times New Roman', serif;
-    line-height: 1.6;
+    max-width: none;
+    font: 16px/1.6 'Source Serif Pro', Georgia, Times, 'Times New Roman', serif;
     color: #333;
 }
 
@@ -28,68 +27,64 @@ h1, h2, h3, h4, h5, h6 {
 @media only screen {
     #toc {
         position: fixed;
-        left: 0px;
-        top: 0px;
-        bottom: 0px;
+        top: 0;
+        left: 0;
+        bottom: 0;
         width: 300px;
         overflow-y: auto;
-        border-right: 1px solid rgba(0, 0, 0, 0.07);
-        padding: 10px 10px;
+        border-right: 1px solid #e8e8e8;
+        padding: 0 15px;
         font-size: 14px;
-        box-sizing: border-box;
-        -webkit-overflow-scrolling: touch;
         background-color: #fafafa;
-        color: #364149;
+        -webkit-overflow-scrolling: touch;
     }
 
     #page-wrapper {
         position: absolute;
-        left: 310px;
-        right: 0px;
-        top: 0px;
-        box-sizing: border-box;
-        background: none repeat scroll 0% 0% #FFF;
+        top: 0;
+        left: 300px;
+        right: 0;
+        padding: 0 15px;
         -webkit-overflow-scrolling: touch;
     }
 }
 
 @media only print {
-    #toc, #nav, #menu-bar {
+    #toc, #nav {
         display: none;
     }
 }
 
-@media only screen and (max-width: 1060px) {
+@media only screen and (max-width: 1023px) {
     #toc {
         width: 100%;
-        margin-right: 0;
         top: 40px;
     }
+
     #page-wrapper {
         top: 40px;
-        left: 15px;
-        padding-right: 15px;
+        left: 0;
     }
+
     .mobile-hidden {
         display: none;
     }
 }
 
 #page {
-    margin-left: auto;
-    margin-right:auto;
+    margin: 0 auto;
     max-width: 750px;
     padding-bottom: 50px;
 }
 
 .chapter {
-    list-style: none outside none;
-    padding-left: 0px;
+    list-style: none;
+    padding-left: 0;
     line-height: 30px;
 }
 
 .section {
-    list-style: none outside none;
+    list-style: none;
     padding-left: 20px;
     line-height: 40px;
 }
@@ -105,28 +100,21 @@ h1, h2, h3, h4, h5, h6 {
     padding: 5px 0;
 }
 
-.chapter li a.active {
-    color: #008cff;
-}
-
+.chapter li a.active,
 .chapter li a:hover {
     color: #008cff;
     text-decoration: none;
 }
 
 #toggle-nav {
-    height: 20px;
-    width:  30px;
-    padding: 3px 3px 0 3px;
-}
-
-#toggle-nav {
+    cursor: pointer;
     margin-top: 5px;
     width: 30px;
     height: 30px;
-    background-color: #FFF;
+    background-color: #fff;
     border: 1px solid #666;
-    border-radius: 3px 3px 3px 3px;
+    border-radius: 3px;
+    padding: 3px 3px 0 3px;
 }
 
 .sr-only {
@@ -151,7 +139,7 @@ h1, h2, h3, h4, h5, h6 {
 }
 
 pre {
-    padding: 16px;
+    padding: 11px;
     overflow: auto;
     font-size: 85%;
     line-height: 1.45;
@@ -160,10 +148,6 @@ pre {
     border-radius: 3px;
 }
 
-.nav-previous-next {
-    margin-top: 60px;
-}
-
 .left {
     float: left;
 }
index fdefab2875926be6c7908f4377c71cbee5bbe7a0..d8ab15260edb47448d08f0290f1695979201ec29 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,66 +8,71 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+/*jslint browser: true, es5: true */
+/*globals $: true, rootPath: true */
 
-document.addEventListener("DOMContentLoaded", function(event) {
+document.addEventListener('DOMContentLoaded', function() {
+    'use strict';
 
-  document.getElementById("toggle-nav").onclick = toggleNav;
+    document.getElementById('toggle-nav').onclick = function(e) {
+        var toc = document.getElementById('toc');
+        var pagewrapper = document.getElementById('page-wrapper');
+        toggleClass(toc, 'mobile-hidden');
+        toggleClass(pagewrapper, 'mobile-hidden');
+    };
 
-  function toggleNav() {
-    var toc = document.getElementById("toc");
-    var pagewrapper = document.getElementById("page-wrapper");
-    toggleClass(toc, "mobile-hidden");
-    toggleClass(pagewrapper, "mobile-hidden");
-  }
+    function toggleClass(el, className) {
+        // from http://youmightnotneedjquery.com/
+        if (el.classList) {
+            el.classList.toggle(className);
+        } else {
+            var classes = el.className.split(' ');
+            var existingIndex = classes.indexOf(className);
 
-  function toggleClass(el, className) {
-     // from http://youmightnotneedjquery.com/
-     if (el.classList) {
-       el.classList.toggle(className);
-     } else {
-       var classes = el.className.split(' ');
-       var existingIndex = classes.indexOf(className);
+            if (existingIndex >= 0) {
+                classes.splice(existingIndex, 1);
+            } else {
+                classes.push(className);
+            }
 
-       if (existingIndex >= 0) {
-         classes.splice(existingIndex, 1);
-       } else {
-         classes.push(className);
-       }
-
-       el.className = classes.join(' ');
-     }
-  }
+            el.className = classes.join(' ');
+        }
+    }
 
-  // The below code is used to add prev and next navigation links to the bottom
-  // of each of the sections.
-  // It works by extracting the current page based on the url and iterates over
-  // the menu links until it finds the menu item for the current page. We then
-  // create a copy of the preceding and following menu links and add the
-  // correct css class and insert them into the bottom of the page.
-  var toc = document.getElementById('toc').getElementsByTagName('a');
-  var href = document.location.pathname.split('/').pop();
-  if (href === 'index.html' || href === '') {
-    href = 'README.html';
-  }
+    // The below code is used to add prev and next navigation links to the
+    // bottom of each of the sections.
+    // It works by extracting the current page based on the url and iterates
+    // over the menu links until it finds the menu item for the current page. We
+    // then create a copy of the preceding and following menu links and add the
+    // correct css class and insert them into the bottom of the page.
+    var toc = document.getElementById('toc').getElementsByTagName('a');
+    var href = document.location.pathname.split('/').pop();
 
-  for (var i = 0; i < toc.length; i++) {
-    if (toc[i].attributes.href.value.split('/').pop() === href) {
-      var nav = document.createElement('p');
-      if (i > 0) {
-        var prevNode = toc[i-1].cloneNode(true);
-        prevNode.className = 'left';
-        prevNode.setAttribute('rel', 'prev');
-        nav.appendChild(prevNode);
-      }
-      if (i < toc.length - 1) {
-        var nextNode = toc[i+1].cloneNode(true);
-        nextNode.className = 'right';
-        nextNode.setAttribute('rel', 'next');
-        nav.appendChild(nextNode);
-      }
-      document.getElementById('page').appendChild(nav);
-      break;
+    if (href === 'index.html' || href === '') {
+        href = 'README.html';
     }
-  }
 
+    for (var i = 0; i < toc.length; i++) {
+        if (toc[i].attributes.href.value.split('/').pop() === href) {
+            var nav = document.createElement('p');
+
+            if (i > 0) {
+                var prevNode = toc[i-1].cloneNode(true);
+                prevNode.className = 'left';
+                prevNode.setAttribute('rel', 'prev');
+                nav.appendChild(prevNode);
+            }
+
+            if (i < toc.length - 1) {
+                var nextNode = toc[i+1].cloneNode(true);
+                nextNode.className = 'right';
+                nextNode.setAttribute('rel', 'next');
+                nav.appendChild(nextNode);
+            }
+
+            document.getElementById('page').appendChild(nav);
+
+            break;
+        }
+    }
 });
index 5a8e1f695ae6e846a9addc9b9d9f795a415ef9ac..a66c2b4f3024dda9bc90bd6c194b876df9555d53 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Common API for all rust-book subcommands.
+//! Common API for all rustbook subcommands.
 
 use error::CliResult;
 use error::CommandResult;
index a40f0a245d17e62c9256a50d119fabc6f34cbf2f..2cf6277e0572275481ec6aa02a7c93a52c0a1ee6 100644 (file)
@@ -163,12 +163,20 @@ LLVMRustWriteArchive(char *Dst,
     auto Member = NewMembers[i];
     assert(Member->name);
     if (Member->filename) {
+#if LLVM_VERSION_MINOR >= 8
+      Members.push_back(NewArchiveIterator(Member->filename));
+#else
       Members.push_back(NewArchiveIterator(Member->filename, Member->name));
+#endif
     } else {
       Members.push_back(NewArchiveIterator(Member->child, Member->name));
     }
   }
+#if LLVM_VERSION_MINOR >= 8
+  auto pair = writeArchive(Dst, Members, WriteSymbtab, Kind, true, false);
+#else
   auto pair = writeArchive(Dst, Members, WriteSymbtab, Kind, true);
+#endif
   if (!pair.second)
     return 0;
   LLVMRustSetLastError(pair.second.message().c_str());
index 6513fdfd2f2c19251df063caab0ada32cd271089..b27a622136f749f90ea50a70e3c459afe7517cf1 100644 (file)
@@ -49,7 +49,9 @@ LLVMInitializePasses() {
   initializeVectorization(Registry);
   initializeIPO(Registry);
   initializeAnalysis(Registry);
+#if LLVM_VERSION_MINOR <= 7
   initializeIPA(Registry);
+#endif
   initializeTransformUtils(Registry);
   initializeInstCombine(Registry);
   initializeInstrumentation(Registry);
@@ -250,7 +252,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
 #endif
   PM->run(*unwrap(M));
 
-  // Apparently `addPassesToEmitFile` adds an pointer to our on-the-stack output
+  // Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output
   // stream (OS), so the only real safe place to delete this is here? Don't we
   // wish this was written in Rust?
   delete PM;
@@ -335,8 +337,7 @@ LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module,
                                        LLVMTargetMachineRef TMR) {
     TargetMachine *Target = unwrap(TMR);
 #if LLVM_VERSION_MINOR >= 7
-    if (const DataLayout *DL = Target->getDataLayout())
-        unwrap(Module)->setDataLayout(*DL);
+    unwrap(Module)->setDataLayout(Target->createDataLayout());
 #elif LLVM_VERSION_MINOR >= 6
     if (const DataLayout *DL = Target->getSubtargetImpl()->getDataLayout())
         unwrap(Module)->setDataLayout(DL);
index 5007af0e777b84bc080f71ebb74cf9945edb1895..5a9c096e5f54339499bbe8a5a14af16c7a8efd6a 100644 (file)
@@ -320,7 +320,9 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateSubroutineType(
     LLVMMetadataRef File,
     LLVMMetadataRef ParameterTypes) {
     return wrap(Builder->createSubroutineType(
+#if LLVM_VERSION_MINOR <= 7
         unwrapDI<DIFile>(File),
+#endif
 #if LLVM_VERSION_MINOR >= 7
         DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
 #elif LLVM_VERSION_MINOR >= 6
@@ -502,11 +504,27 @@ extern "C" LLVMMetadataRef LLVMDIBuilderCreateVariable(
         ));
     }
 #endif
+#if LLVM_VERSION_MINOR >= 8
+    if (Tag == 0x100) { // DW_TAG_auto_variable
+        return wrap(Builder->createAutoVariable(
+            unwrapDI<DIDescriptor>(Scope), Name,
+            unwrapDI<DIFile>(File),
+            LineNo,
+            unwrapDI<DIType>(Ty), AlwaysPreserve, Flags));
+    } else {
+        return wrap(Builder->createParameterVariable(
+            unwrapDI<DIDescriptor>(Scope), Name, ArgNo,
+            unwrapDI<DIFile>(File),
+            LineNo,
+            unwrapDI<DIType>(Ty), AlwaysPreserve, Flags));
+    }
+#else
     return wrap(Builder->createLocalVariable(Tag,
         unwrapDI<DIDescriptor>(Scope), Name,
         unwrapDI<DIFile>(File),
         LineNo,
         unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, ArgNo));
+#endif
 }
 
 extern "C" LLVMMetadataRef LLVMDIBuilderCreateArrayType(
@@ -951,10 +969,5 @@ LLVMRustBuildLandingPad(LLVMBuilderRef Builder,
                         unsigned NumClauses,
                         const char* Name,
                         LLVMValueRef F) {
-#if LLVM_VERSION_MINOR >= 7
-    unwrap<Function>(F)->setPersonalityFn(unwrap<Constant>(PersFn));
-    return LLVMBuildLandingPad(Builder, Ty, NumClauses, Name);
-#else
     return LLVMBuildLandingPad(Builder, Ty, PersFn, NumClauses, Name);
-#endif
 }
index df9dc8bc8418026dfd0847ce6b7cfdeacd0af00b..4ef1fbb506bbb0e3ac197a053d7fe36f8dd482ed 100644 (file)
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2015-09-11
+2015-12-02
diff --git a/src/test/auxiliary/augmented_assignments.rs b/src/test/auxiliary/augmented_assignments.rs
new file mode 100644 (file)
index 0000000..9577e1f
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(augmented_assignments)]
+#![feature(op_assign_traits)]
+
+use std::ops::AddAssign;
+
+pub struct Int(i32);
+
+impl AddAssign<i32> for Int {
+    fn add_assign(&mut self, _: i32) {
+        unimplemented!();
+    }
+}
index d9be03c094c49da670e9070168a411d17c825b82..9b6b6221bda38ce17be49d6c3f56c3b7b3c540b3 100644 (file)
@@ -11,6 +11,7 @@
 #![crate_type = "rlib"]
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 // no-prefer-dynamic
index f4e6f6d7511a8a20f012cfa0b499e031d454933d..60477288f7cb090312fc6d095be258367a5a8b08 100644 (file)
@@ -29,7 +29,7 @@ pub mod stable_mod {
 #[unstable(feature = "test_feature", issue = "0")]
 pub mod unstable_mod {
     #[stable(feature = "test_feature", since = "1.0.0")]
-    #[deprecated(since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     pub fn deprecated() {}
 
     pub fn unstable() {}
index 96f33f97a696973c891a36bbe0e0a742f5598bf9..cfebc4abaaa6150d0c8689c82c5bb7368812b278 100644 (file)
@@ -22,5 +22,5 @@ pub trait i<T>
 pub fn f<T>() -> Box<i<T>+'static> {
     impl<T> i<T> for () { }
 
-    box() () as Box<i<T>+'static>
+    box () as Box<i<T>+'static>
 }
diff --git a/src/test/auxiliary/issue-29181.rs b/src/test/auxiliary/issue-29181.rs
new file mode 100644 (file)
index 0000000..361f1ea
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type="lib"]
+
+pub mod foo {
+    pub use super::*;
+}
index 708fcafcb53112d00a02d67f09538f15fd876c64..7ae161a86a3614254472364026e3575a72540d0b 100644 (file)
 
 #[macro_use] extern crate rustc;
 extern crate rustc_front;
+extern crate syntax;
 
-use rustc::lint::{Context, LintPass, LintPassObject, LintArray};
+use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray};
 use rustc::plugin::Registry;
-use rustc_front::{hir, attr};
+use rustc_front::hir;
+use syntax::attr;
 
 declare_lint!(CRATE_NOT_OKAY, Warn, "crate not marked with #![crate_okay]");
 
@@ -28,8 +30,10 @@ impl LintPass for Pass {
     fn get_lints(&self) -> LintArray {
         lint_array!(CRATE_NOT_OKAY)
     }
+}
 
-    fn check_crate(&mut self, cx: &Context, krate: &hir::Crate) {
+impl LateLintPass for Pass {
+    fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) {
         if !attr::contains_name(&krate.attrs, "crate_okay") {
             cx.span_lint(CRATE_NOT_OKAY, krate.span,
                          "crate is not marked with #![crate_okay]");
@@ -39,5 +43,5 @@ impl LintPass for Pass {
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_lint_pass(box Pass as LintPassObject);
+    reg.register_late_lint_pass(box Pass as LateLintPassObject);
 }
index adc194fa454862a40eab10a6b56279e22b335ca4..81bd76211c3f854b8f8de5ef70e25ede3863f603 100644 (file)
@@ -20,7 +20,7 @@ extern crate rustc_front;
 extern crate rustc;
 
 use rustc_front::hir;
-use rustc::lint::{Context, LintPass, LintPassObject, LintArray};
+use rustc::lint::{LateContext, LintContext, LintPass, LateLintPass, LateLintPassObject, LintArray};
 use rustc::plugin::Registry;
 
 declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
@@ -33,9 +33,11 @@ impl LintPass for Pass {
     fn get_lints(&self) -> LintArray {
         lint_array!(TEST_LINT, PLEASE_LINT)
     }
+}
 
-    fn check_item(&mut self, cx: &Context, it: &hir::Item) {
-        match &*it.ident.name.as_str() {
+impl LateLintPass for Pass {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+        match &*it.name.as_str() {
             "lintme" => cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'"),
             "pleaselintme" => cx.span_lint(PLEASE_LINT, it.span, "item is named 'pleaselintme'"),
             _ => {}
@@ -45,6 +47,6 @@ impl LintPass for Pass {
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_lint_pass(box Pass as LintPassObject);
+    reg.register_late_lint_pass(box Pass as LateLintPassObject);
     reg.register_lint_group("lint_me", vec![TEST_LINT, PLEASE_LINT]);
 }
index 51fad3ce3cd6939f0df2f8922e04c80e3910d3ed..8794119a869cea83e62965bb06ca4ae14867a35e 100644 (file)
@@ -15,7 +15,7 @@
 #![unstable(feature = "test_feature", issue = "0")]
 
 #[stable(feature = "test_feature", since = "1.0.0")]
-#[deprecated(since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "text")]
 pub fn foo() -> usize {
     20
 }
index e6f91db230009af05c3411ad9842129f47b62e50..a0036745d90a432f3be9ea1d83780e5bf1a0e5e3 100644 (file)
 #![feature(plugin_registrar)]
 #![feature(box_syntax, rustc_private)]
 
-extern crate rustc_front;
+extern crate syntax;
 
 // Load rustc as a plugin to get macros
 #[macro_use]
 extern crate rustc;
 
-use rustc::lint::{Context, LintPass, LintPassObject, LintArray};
+use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass,
+                  EarlyLintPassObject, LintArray};
 use rustc::plugin::Registry;
-use rustc_front::hir;
+use syntax::ast;
 declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
 
 struct Pass;
@@ -30,9 +31,11 @@ impl LintPass for Pass {
     fn get_lints(&self) -> LintArray {
         lint_array!(TEST_LINT)
     }
+}
 
-    fn check_item(&mut self, cx: &Context, it: &hir::Item) {
-        if it.ident.name == "lintme" {
+impl EarlyLintPass for Pass {
+    fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
+        if it.ident.name.as_str() == "lintme" {
             cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'");
         }
     }
@@ -40,5 +43,5 @@ impl LintPass for Pass {
 
 #[plugin_registrar]
 pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_lint_pass(box Pass as LintPassObject);
+    reg.register_early_lint_pass(box Pass as EarlyLintPassObject);
 }
index 60097393a259615a6827367f4e995b4f07b8ef3d..260361634ae8734a42dca56d38f534867818e194 100644 (file)
 #![stable(feature = "lint_stability", since = "1.0.0")]
 
 #[stable(feature = "test_feature", since = "1.0.0")]
-#[deprecated(since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "text")]
 pub fn deprecated() {}
 #[stable(feature = "test_feature", since = "1.0.0")]
 #[deprecated(since = "1.0.0", reason = "text")]
 pub fn deprecated_text() {}
 
 #[unstable(feature = "test_feature", issue = "0")]
-#[deprecated(since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "text")]
 pub fn deprecated_unstable() {}
 #[unstable(feature = "test_feature", issue = "0")]
 #[deprecated(since = "1.0.0", reason = "text")]
@@ -34,7 +34,7 @@ pub fn unstable_text() {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stable() {}
-#[stable(feature = "rust1", since = "1.0.0", reason = "text")]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub fn stable_text() {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -42,14 +42,14 @@ pub struct MethodTester;
 
 impl MethodTester {
     #[stable(feature = "test_feature", since = "1.0.0")]
-    #[deprecated(since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     pub fn method_deprecated(&self) {}
     #[stable(feature = "test_feature", since = "1.0.0")]
     #[deprecated(since = "1.0.0", reason = "text")]
     pub fn method_deprecated_text(&self) {}
 
     #[unstable(feature = "test_feature", issue = "0")]
-    #[deprecated(since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     pub fn method_deprecated_unstable(&self) {}
     #[unstable(feature = "test_feature", issue = "0")]
     #[deprecated(since = "1.0.0", reason = "text")]
@@ -62,21 +62,21 @@ impl MethodTester {
 
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn method_stable(&self) {}
-    #[stable(feature = "rust1", since = "1.0.0", reason = "text")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn method_stable_text(&self) {}
 }
 
 #[stable(feature = "test_feature", since = "1.0.0")]
 pub trait Trait {
     #[stable(feature = "test_feature", since = "1.0.0")]
-    #[deprecated(since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     fn trait_deprecated(&self) {}
     #[stable(feature = "test_feature", since = "1.0.0")]
     #[deprecated(since = "1.0.0", reason = "text")]
     fn trait_deprecated_text(&self) {}
 
     #[unstable(feature = "test_feature", issue = "0")]
-    #[deprecated(since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     fn trait_deprecated_unstable(&self) {}
     #[unstable(feature = "test_feature", issue = "0")]
     #[deprecated(since = "1.0.0", reason = "text")]
@@ -89,7 +89,7 @@ pub trait Trait {
 
     #[stable(feature = "rust1", since = "1.0.0")]
     fn trait_stable(&self) {}
-    #[stable(feature = "rust1", since = "1.0.0", reason = "text")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn trait_stable_text(&self) {}
 }
 
@@ -99,12 +99,12 @@ impl Trait for MethodTester {}
 pub trait UnstableTrait { fn dummy(&self) { } }
 
 #[stable(feature = "test_feature", since = "1.0.0")]
-#[deprecated(since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "text")]
 pub struct DeprecatedStruct {
     #[stable(feature = "test_feature", since = "1.0.0")] pub i: isize
 }
 #[unstable(feature = "test_feature", issue = "0")]
-#[deprecated(since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "text")]
 pub struct DeprecatedUnstableStruct {
     #[stable(feature = "test_feature", since = "1.0.0")] pub i: isize
 }
@@ -118,10 +118,10 @@ pub struct StableStruct {
 }
 
 #[stable(feature = "test_feature", since = "1.0.0")]
-#[deprecated(since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "text")]
 pub struct DeprecatedUnitStruct;
 #[unstable(feature = "test_feature", issue = "0")]
-#[deprecated(since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "text")]
 pub struct DeprecatedUnstableUnitStruct;
 #[unstable(feature = "test_feature", issue = "0")]
 pub struct UnstableUnitStruct;
@@ -131,10 +131,10 @@ pub struct StableUnitStruct;
 #[stable(feature = "test_feature", since = "1.0.0")]
 pub enum Enum {
     #[stable(feature = "test_feature", since = "1.0.0")]
-    #[deprecated(since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     DeprecatedVariant,
     #[unstable(feature = "test_feature", issue = "0")]
-    #[deprecated(since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     DeprecatedUnstableVariant,
     #[unstable(feature = "test_feature", issue = "0")]
     UnstableVariant,
@@ -144,10 +144,10 @@ pub enum Enum {
 }
 
 #[stable(feature = "test_feature", since = "1.0.0")]
-#[deprecated(since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "text")]
 pub struct DeprecatedTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
 #[unstable(feature = "test_feature", issue = "0")]
-#[deprecated(since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "text")]
 pub struct DeprecatedUnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
 #[unstable(feature = "test_feature", issue = "0")]
 pub struct UnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
index b45af89dd3b73a47d8702c474d73061be1a98888..44b4abd38b85a6180bdf7aade37361cf2b5f6a87 100644 (file)
@@ -18,7 +18,7 @@ pub struct Stable {
     pub inherit: u8, // it's a lie (stable doesn't inherit)
     #[unstable(feature = "test_feature", issue = "0")]
     pub override1: u8,
-    #[deprecated(since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     #[unstable(feature = "test_feature", issue = "0")]
     pub override2: u8,
 }
@@ -27,14 +27,14 @@ pub struct Stable {
 pub struct Stable2(#[stable(feature = "rust1", since = "1.0.0")] pub u8,
                    #[unstable(feature = "test_feature", issue = "0")] pub u8,
                    #[unstable(feature = "test_feature", issue = "0")]
-                   #[deprecated(since = "1.0.0")] pub u8);
+                   #[deprecated(since = "1.0.0", reason = "text")] pub u8);
 
 #[unstable(feature = "test_feature", issue = "0")]
 pub struct Unstable {
     pub inherit: u8,
     #[stable(feature = "rust1", since = "1.0.0")]
     pub override1: u8,
-    #[deprecated(since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     #[unstable(feature = "test_feature", issue = "0")]
     pub override2: u8,
 }
@@ -43,10 +43,10 @@ pub struct Unstable {
 pub struct Unstable2(pub u8,
                      #[stable(feature = "rust1", since = "1.0.0")] pub u8,
                      #[unstable(feature = "test_feature", issue = "0")]
-                     #[deprecated(since = "1.0.0")] pub u8);
+                     #[deprecated(since = "1.0.0", reason = "text")] pub u8);
 
 #[unstable(feature = "test_feature", issue = "0")]
-#[deprecated(feature = "rust1", since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "text")]
 pub struct Deprecated {
     pub inherit: u8,
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -56,7 +56,7 @@ pub struct Deprecated {
 }
 
 #[unstable(feature = "test_feature", issue = "0")]
-#[deprecated(feature = "rust1", since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "text")]
 pub struct Deprecated2(pub u8,
                        #[stable(feature = "rust1", since = "1.0.0")] pub u8,
                        #[unstable(feature = "test_feature", issue = "0")] pub u8);
index 8c7ad2293e23db67cd051db94533e334486b6c07..296d1e431f4ca20dcd037189745db0c130cff6d0 100644 (file)
@@ -33,7 +33,7 @@ fn expand_mbe_matches(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
 
     let mac_expr = match TokenTree::parse(cx, &mbe_matcher[..], args) {
         Success(map) => {
-            match (&*map[&str_to_ident("matched")], &*map[&str_to_ident("pat")]) {
+            match (&*map[&str_to_ident("matched").name], &*map[&str_to_ident("pat").name]) {
                 (&MatchedNonterminal(NtExpr(ref matched_expr)),
                  &MatchedSeq(ref pats, seq_sp)) => {
                     let pats: Vec<P<Pat>> = pats.iter().map(|pat_nt|
index d62b98714026bd5ce78a7afa5b506eecc7cbb067..c57d161d8f574b7016dc21fa6c0520248340d1eb 100644 (file)
@@ -13,5 +13,4 @@ pub fn cci_fn() -> usize {
     1200
 }
 
-#[inline]
-pub static CCI_STATIC: usize = 34;
+pub const CCI_CONST: usize = 34;
index 652f11a71ec6f6d82ed403e4c76932e80202753f..d0da80e31b913d732ead23a3c910444a7a6ff573 100644 (file)
@@ -8,13 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[inline(never)]
 pub static global: isize = 3;
 
-#[inline(never)]
 static global0: isize = 4;
 
-#[inline(never)]
 pub static global2: &'static isize = &global0;
 
 pub fn verify_same(a: &'static isize) {
index ebb8036bacf1b18c5b8c1efefcd87bccf2d2761e..a72e348c7201865a43c4fa25e9ce3612a271291c 100644 (file)
@@ -126,8 +126,7 @@ fn main() {
 
     println!("{} keys", n_keys);
 
-    // FIXME: #9970
-    println!("{}", "\nBTreeMap:");
+    println!("\nBTreeMap:");
 
     {
         let mut map: BTreeMap<usize,usize> = BTreeMap::new();
@@ -145,8 +144,7 @@ fn main() {
         vector(&mut map, n_keys, &rand);
     }
 
-    // FIXME: #9970
-    println!("{}", "\nHashMap:");
+    println!("\nHashMap:");
 
     {
         let mut map: HashMap<usize,usize> = HashMap::new();
index 963a007c6855a0990a75aeb0ebaa1a0ec3a44f42..6d64c50b826b58c9cfc8f616b9f426af1b13a7b0 100644 (file)
 // OF THE POSSIBILITY OF SUCH DAMAGE.
 
 use std::cmp::min;
-use std::env;
-use std::io;
-use std::io::prelude::*;
+use std::io::{self, Write};
+use std::sync::{Arc, Mutex};
+use std::thread;
+
 
 const LINE_LEN: usize = 60;
+
+const BLOCK_LINES: usize = 512;
+const BLOCK_THOROUGHPUT: usize = LINE_LEN * BLOCK_LINES;
+const BLOCK_LEN: usize = BLOCK_THOROUGHPUT + BLOCK_LINES;
+
+const STDIN_BUF: usize = (LINE_LEN + 1) * 1024;
 const LOOKUP_SIZE: usize = 4 * 1024;
 const LOOKUP_SCALE: f32 = (LOOKUP_SIZE - 1) as f32;
 
-// Random number generator constants
-const IM: u32 = 139968;
-const IA: u32 = 3877;
-const IC: u32 = 29573;
-
-const ALU: &'static str = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG\
-                            GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA\
-                            GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA\
-                            AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT\
-                            CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC\
-                            CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG\
-                            CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
-
-const NULL_AMINO_ACID: AminoAcid = AminoAcid { c: ' ' as u8, p: 0.0 };
-
-static IUB: [AminoAcid;15] = [
-    AminoAcid { c: 'a' as u8, p: 0.27 },
-    AminoAcid { c: 'c' as u8, p: 0.12 },
-    AminoAcid { c: 'g' as u8, p: 0.12 },
-    AminoAcid { c: 't' as u8, p: 0.27 },
-    AminoAcid { c: 'B' as u8, p: 0.02 },
-    AminoAcid { c: 'D' as u8, p: 0.02 },
-    AminoAcid { c: 'H' as u8, p: 0.02 },
-    AminoAcid { c: 'K' as u8, p: 0.02 },
-    AminoAcid { c: 'M' as u8, p: 0.02 },
-    AminoAcid { c: 'N' as u8, p: 0.02 },
-    AminoAcid { c: 'R' as u8, p: 0.02 },
-    AminoAcid { c: 'S' as u8, p: 0.02 },
-    AminoAcid { c: 'V' as u8, p: 0.02 },
-    AminoAcid { c: 'W' as u8, p: 0.02 },
-    AminoAcid { c: 'Y' as u8, p: 0.02 },
-];
-
-static HOMO_SAPIENS: [AminoAcid;4] = [
-    AminoAcid { c: 'a' as u8, p: 0.3029549426680 },
-    AminoAcid { c: 'c' as u8, p: 0.1979883004921 },
-    AminoAcid { c: 'g' as u8, p: 0.1975473066391 },
-    AminoAcid { c: 't' as u8, p: 0.3015094502008 },
-];
-
-fn sum_and_scale(a: &'static [AminoAcid]) -> Vec<AminoAcid> {
-    let mut p = 0f32;
-    let mut result: Vec<AminoAcid> = a.iter().map(|a_i| {
-        p += a_i.p;
-        AminoAcid { c: a_i.c, p: p * LOOKUP_SCALE }
-    }).collect();
-    let result_len = result.len();
-    result[result_len - 1].p = LOOKUP_SCALE;
-    result
-}
+const ALU: &'static [u8] =
+    b"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG\
+      GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA\
+      CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT\
+      ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA\
+      GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG\
+      AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC\
+      AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
+
+const IUB: &'static [(u8, f32)] =
+    &[(b'a', 0.27), (b'c', 0.12), (b'g', 0.12),
+      (b't', 0.27), (b'B', 0.02), (b'D', 0.02),
+      (b'H', 0.02), (b'K', 0.02), (b'M', 0.02),
+      (b'N', 0.02), (b'R', 0.02), (b'S', 0.02),
+      (b'V', 0.02), (b'W', 0.02), (b'Y', 0.02)];
+
+const HOMOSAPIENS: &'static [(u8, f32)] =
+    &[(b'a', 0.3029549426680),
+      (b'c', 0.1979883004921),
+      (b'g', 0.1975473066391),
+      (b't', 0.3015094502008)];
+
+// We need a specific Rng,
+// so implement this manually
+
+const MODULUS: u32 = 139968;
+const MULTIPLIER: u32 = 3877;
+const ADDITIVE: u32 = 29573;
+
+// Why doesn't rust already have this?
+// Algorithm directly taken from Wikipedia
+fn powmod(mut base: u64, mut exponent: u32, modulus: u64) -> u64 {
+    let mut ret = 1;
+    base %= modulus;
 
-#[derive(Copy, Clone)]
-struct AminoAcid {
-    c: u8,
-    p: f32,
+    while exponent > 0 {
+        if exponent & 1 == 1 {
+           ret *= base;
+           ret %= modulus;
+        }
+        exponent >>= 1;
+        base *= base;
+        base %= modulus;
+    }
+
+    ret
 }
 
-struct RepeatFasta<'a, W:'a> {
-    alu: &'static str,
-    out: &'a mut W
+// Just a typical LCRNG
+pub struct Rng {
+    last: u32
 }
 
-impl<'a, W: Write> RepeatFasta<'a, W> {
-    fn new(alu: &'static str, w: &'a mut W) -> RepeatFasta<'a, W> {
-        RepeatFasta { alu: alu, out: w }
+impl Rng {
+    pub fn new() -> Rng {
+        Rng { last: 42 }
     }
 
-    fn make(&mut self, n: usize) -> io::Result<()> {
-        let alu_len = self.alu.len();
-        let mut buf = vec![0; alu_len + LINE_LEN];
-        let alu: &[u8] = self.alu.as_bytes();
+    pub fn max_value() -> u32 {
+        MODULUS - 1
+    }
 
-        for (slot, val) in buf.iter_mut().zip(alu) {
-            *slot = *val;
-        }
-        let buf_len = buf.len();
-        for (slot, val) in buf[alu_len..buf_len].iter_mut().zip(&alu[..LINE_LEN]) {
-            *slot = *val;
-        }
+    pub fn normalize(p: f32) -> u32 {
+        (p * MODULUS as f32).floor() as u32
+    }
 
-        let mut pos = 0;
-        let mut bytes;
-        let mut n = n;
-        while n > 0 {
-            bytes = min(LINE_LEN, n);
-            try!(self.out.write_all(&buf[pos..pos + bytes]));
-            try!(self.out.write_all(&[b'\n']));
-            pos += bytes;
-            if pos > alu_len {
-                pos -= alu_len;
-            }
-            n -= bytes;
-        }
-        Ok(())
+    pub fn gen(&mut self) -> u32 {
+        self.last = (self.last * MULTIPLIER + ADDITIVE) % MODULUS;
+        self.last
     }
-}
 
-fn make_lookup(a: &[AminoAcid]) -> [AminoAcid;LOOKUP_SIZE] {
-    let mut lookup = [ NULL_AMINO_ACID;LOOKUP_SIZE ];
-    let mut j = 0;
-    for (i, slot) in lookup.iter_mut().enumerate() {
-        while a[j].p < (i as f32) {
-            j += 1;
-        }
-        *slot = a[j];
+    // This allows us to fast-forward the RNG,
+    // allowing us to run it in parallel.
+    pub fn future(&self, n: u32) -> Rng {
+        let a = MULTIPLIER as u64;
+        let b = ADDITIVE as u64;
+        let m = MODULUS as u64;
+
+        //                          (a^n - 1) mod (a-1) m
+        // x_k = ((a^n x_0 mod m) + --------------------- b) mod m
+        //                                   a - 1
+        //
+        // Since (a - 1) divides (a^n - 1) mod (a-1) m,
+        // the subtraction does not overflow and thus can be non-modular.
+        //
+        let new_seed =
+            (powmod(a, n, m) * self.last as u64) % m +
+            (powmod(a, n, (a-1) * m) - 1) / (a-1) * b;
+
+        Rng { last: (new_seed % m) as u32 }
     }
-    lookup
 }
 
-struct RandomFasta<'a, W:'a> {
-    seed: u32,
-    lookup: [AminoAcid;LOOKUP_SIZE],
-    out: &'a mut W,
+
+// This will end up keeping track of threads, like
+// in the other multithreaded Rust version, in
+// order to keep writes in order.
+//
+// This is stolen from another multithreaded Rust
+// implementation, although that implementation
+// was not able to parallelize the RNG itself.
+struct BlockSubmitter<W: io::Write> {
+    writer: W,
+    pub waiting_on: usize,
 }
 
-impl<'a, W: Write> RandomFasta<'a, W> {
-    fn new(w: &'a mut W, a: &[AminoAcid]) -> RandomFasta<'a, W> {
-        RandomFasta {
-            seed: 42,
-            out: w,
-            lookup: make_lookup(a),
+impl<W: io::Write> BlockSubmitter<W> {
+    fn submit(&mut self, data: &[u8], block_num: usize) -> Option<io::Result<()>> {
+        if block_num == self.waiting_on {
+            self.waiting_on += 1;
+            Some(self.submit_async(data))
+        }
+        else {
+            None
         }
     }
 
-    fn rng(&mut self, max: f32) -> f32 {
-        self.seed = (self.seed * IA + IC) % IM;
-        (max * self.seed as f32) / (IM as f32)
+    fn submit_async(&mut self, data: &[u8]) -> io::Result<()> {
+        self.writer.write_all(data)
     }
+}
+
+
+// For repeating strings as output
+fn fasta_static<W: io::Write>(
+    writer: &mut W,
+    header: &[u8],
+    data: &[u8],
+    mut n: usize
+) -> io::Result<()>
+{
+    // The aim here is to print a short(ish) string cyclically
+    // with line breaks as appropriate.
+    //
+    // The secret technique is to repeat the string such that
+    // any wanted line is a single offset in the string.
+    //
+    // This technique is stolen from the Haskell version.
+
+    try!(writer.write_all(header));
 
-    fn nextc(&mut self) -> u8 {
-        let r = self.rng(LOOKUP_SCALE);
-        for i in (r as usize..LOOKUP_SIZE) {
-            if self.lookup[i].p >= r {
-                return self.lookup[i].c;
+    // Maximum offset is data.len(),
+    // Maximum read len is LINE_LEN
+    let stream = data.iter().cloned().cycle();
+    let mut extended: Vec<u8> = stream.take(data.len() + LINE_LEN + 1).collect();
+
+    let mut offset = 0;
+    while n > 0 {
+        let write_len = min(LINE_LEN, n);
+        let end = offset + write_len;
+        n -= write_len;
+
+        let tmp = extended[end];
+        extended[end] = b'\n';
+        try!(writer.write_all(&extended[offset..end + 1]));
+        extended[end] = tmp;
+
+        offset = end;
+        offset %= data.len();
+    }
+
+    Ok(())
+}
+
+
+// For RNG streams as output
+fn fasta<W: io::Write + Send + 'static>(
+    submitter: &Arc<Mutex<BlockSubmitter<W>>>,
+    header: &[u8],
+    table: &'static [(u8, f32)],
+    rng: &mut Rng,
+    n: usize
+) -> io::Result<()>
+{
+    // Here the lookup table is part of the algorithm and needs the
+    // original probabilities (scaled with the LOOKUP_SCALE), because
+    // Isaac says so :-)
+    fn sum_and_scale(a: &'static [(u8, f32)]) -> Vec<(u8, f32)> {
+        let mut p = 0f32;
+        let mut result: Vec<(u8, f32)> = a.iter().map(|e| {
+            p += e.1;
+            (e.0, p * LOOKUP_SCALE)
+        }).collect();
+        let result_len = result.len();
+        result[result_len - 1].1 = LOOKUP_SCALE;
+        result
+    }
+
+    fn make_lookup(a: &[(u8, f32)]) -> [(u8, f32); LOOKUP_SIZE] {
+        let mut lookup = [(0, 0f32); LOOKUP_SIZE];
+        let mut j = 0;
+        for (i, slot) in lookup.iter_mut().enumerate() {
+            while a[j].1 < (i as f32) {
+                j += 1;
             }
+            *slot = a[j];
         }
-        unreachable!();
+        lookup
+    }
+
+    {
+        try!(submitter.lock().unwrap().submit_async(header));
+    }
+
+    let lookup_table = Arc::new(make_lookup(&sum_and_scale(table)));
+
+    let thread_count = 4;
+    let mut threads = Vec::new();
+    for block_num in (0..thread_count) {
+        let offset = BLOCK_THOROUGHPUT * block_num;
+
+        let local_submitter = submitter.clone();
+        let local_lookup_table = lookup_table.clone();
+        let local_rng = rng.future(offset as u32);
+
+        threads.push(thread::spawn(move || {
+            gen_block(
+                local_submitter,
+                local_lookup_table,
+                local_rng,
+                n.saturating_sub(offset),
+                block_num,
+                thread_count
+            )
+        }));
+    }
+
+    for thread in threads {
+        try!(thread.join().unwrap());
     }
 
-    fn make(&mut self, n: usize) -> io::Result<()> {
-        let lines = n / LINE_LEN;
-        let chars_left = n % LINE_LEN;
-        let mut buf = [0;LINE_LEN + 1];
+    *rng = rng.future(n as u32);
 
-        for _ in 0..lines {
-            for i in 0..LINE_LEN {
-                buf[i] = self.nextc();
+    Ok(())
+}
+
+// A very optimized writer.
+// I have a feeling a simpler version wouldn't slow
+// things down too much, though, since the RNG
+// is the really heavy hitter.
+fn gen_block<W: io::Write>(
+    submitter: Arc<Mutex<BlockSubmitter<W>>>,
+    lookup_table: Arc<[(u8, f32)]>,
+    mut rng: Rng,
+    mut length: usize,
+    mut block_num: usize,
+    block_stride: usize,
+) -> io::Result<()>
+{
+    // Include newlines in block
+    length += length / LINE_LEN;
+    let block: &mut [u8] = &mut [b'\n'; BLOCK_LEN];
+
+    while length > 0 {
+        {
+            let gen_into = &mut block[..min(length, BLOCK_LEN)];
+
+            // Write random numbers, skipping newlines
+            for (i, byte) in gen_into.iter_mut().enumerate() {
+                if (i + 1) % (LINE_LEN + 1) != 0 {
+                    let p = rng.gen() as f32 * (LOOKUP_SCALE / MODULUS as f32);
+                    *byte = lookup_table[p as usize..LOOKUP_SIZE].iter().find(
+                        |le| le.1 >= p).unwrap().0;
+                }
             }
-            buf[LINE_LEN] = '\n' as u8;
-            try!(self.out.write(&buf));
         }
-        for i in 0..chars_left {
-            buf[i] = self.nextc();
+
+        let write_out = {
+            if length >= BLOCK_LEN               { &mut *block }
+            else if length % (LINE_LEN + 1) == 0 { &mut block[..length] }
+            else                                 { &mut block[..length + 1] }
+        };
+
+        *write_out.last_mut().unwrap() = b'\n';
+        loop {
+            // Make sure to release lock before calling `yield_now`
+            let res = { submitter.lock().unwrap().submit(write_out, block_num) };
+
+            match res {
+                Some(result) => { try!(result); break; }
+                None => std::thread::yield_now()
+            }
         }
-        self.out.write_all(&buf[..chars_left])
+        block_num += block_stride;
+        rng = rng.future((BLOCK_THOROUGHPUT * (block_stride - 1)) as u32);
+        length = length.saturating_sub(BLOCK_LEN * (block_stride - 1));
+
+        length = length.saturating_sub(BLOCK_LEN);
     }
+
+    Ok(())
 }
 
-fn main() {
-    let mut args = env::args();
-    let n = if args.len() > 1 {
-        args.nth(1).unwrap().parse::<usize>().unwrap()
-    } else {
-        5
-    };
+fn run<W: io::Write + Send + 'static>(writer: W) -> io::Result<()> {
+    let n = std::env::args_os().nth(1)
+        .and_then(|s| s.into_string().ok())
+        .and_then(|n| n.parse().ok())
+        .unwrap_or(1000);
 
-    let stdout = io::stdout();
-    let mut out = stdout.lock();
+    let rng = &mut Rng::new();
 
-    out.write_all(b">ONE Homo sapiens alu\n").unwrap();
-    {
-        let mut repeat = RepeatFasta::new(ALU, &mut out);
-        repeat.make(n * 2).unwrap();
-    }
+    // Use automatic buffering for the static version...
+    let mut writer = io::BufWriter::with_capacity(STDIN_BUF, writer);
+    try!(fasta_static(&mut writer, b">ONE Homo sapiens alu\n", ALU, n * 2));
+
+    // ...but the dynamic version does its own buffering already
+    let writer = try!(writer.into_inner());
+    let submitter = Arc::new(Mutex::new(BlockSubmitter { writer: writer, waiting_on: 0 }));
 
-    out.write_all(b">TWO IUB ambiguity codes\n").unwrap();
-    let iub = sum_and_scale(&IUB);
-    let mut random = RandomFasta::new(&mut out, &iub);
-    random.make(n * 3).unwrap();
+    { submitter.lock().unwrap().waiting_on = 0; }
+    try!(fasta(&submitter, b">TWO IUB ambiguity codes\n", &IUB, rng, n * 3));
+    { submitter.lock().unwrap().waiting_on = 0; }
+    try!(fasta(&submitter, b">THREE Homo sapiens frequency\n", &HOMOSAPIENS, rng, n * 5));
 
-    random.out.write_all(b">THREE Homo sapiens frequency\n").unwrap();
-    let homo_sapiens = sum_and_scale(&HOMO_SAPIENS);
-    random.lookup = make_lookup(&homo_sapiens);
-    random.make(n * 5).unwrap();
+    Ok(())
+}
 
-    random.out.write_all(b"\n").unwrap();
+fn main() {
+    run(io::stdout()).unwrap()
 }
index accf525b4e6386ffe1e97faf4ea3189dd2c6f405..a5731f150c6d024c6ef78cc3daccd02521e1c9b3 100644 (file)
 // OF THE POSSIBILITY OF SUCH DAMAGE.
 
 use std::cmp::min;
-use std::env;
-use std::fs::File;
-use std::io::{self, BufWriter};
-use std::io::prelude::*;
+use std::io::{self, Write};
+use std::sync::{Arc, Mutex};
+use std::thread;
 
-const LINE_LENGTH: usize = 60;
-const IM: u32 = 139968;
 
-struct MyRandom {
+const LINE_LEN: usize = 60;
+
+const BLOCK_LINES: usize = 512;
+const BLOCK_THOROUGHPUT: usize = LINE_LEN * BLOCK_LINES;
+const BLOCK_LEN: usize = BLOCK_THOROUGHPUT + BLOCK_LINES;
+
+const STDIN_BUF: usize = (LINE_LEN + 1) * 1024;
+
+
+const ALU: &'static [u8] =
+    b"GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG\
+      GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA\
+      CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT\
+      ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA\
+      GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG\
+      AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC\
+      AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
+
+const IUB: &'static [(u8, f32)] =
+    &[(b'a', 0.27), (b'c', 0.12), (b'g', 0.12),
+      (b't', 0.27), (b'B', 0.02), (b'D', 0.02),
+      (b'H', 0.02), (b'K', 0.02), (b'M', 0.02),
+      (b'N', 0.02), (b'R', 0.02), (b'S', 0.02),
+      (b'V', 0.02), (b'W', 0.02), (b'Y', 0.02)];
+
+const HOMOSAPIENS: &'static [(u8, f32)] =
+    &[(b'a', 0.3029549426680),
+      (b'c', 0.1979883004921),
+      (b'g', 0.1975473066391),
+      (b't', 0.3015094502008)];
+
+
+// We need a specific Rng,
+// so implement this manually
+const MODULUS: u32 = 139968;
+const MULTIPLIER: u32 = 3877;
+const ADDITIVE: u32 = 29573;
+
+// Why doesn't rust already have this?
+// Algorithm directly taken from Wikipedia
+fn powmod(mut base: u64, mut exponent: u32, modulus: u64) -> u64 {
+    let mut ret = 1;
+    base %= modulus;
+
+    while exponent > 0 {
+        if exponent & 1 == 1 {
+           ret *= base;
+           ret %= modulus;
+        }
+        exponent >>= 1;
+        base *= base;
+        base %= modulus;
+    }
+
+    ret
+}
+
+// Just a typical LCRNG
+pub struct Rng {
     last: u32
 }
-impl MyRandom {
-    fn new() -> MyRandom { MyRandom { last: 42 } }
-    fn normalize(p: f32) -> u32 {(p * IM as f32).floor() as u32}
-    fn gen(&mut self) -> u32 {
-        self.last = (self.last * 3877 + 29573) % IM;
+
+impl Rng {
+    pub fn new() -> Rng {
+        Rng { last: 42 }
+    }
+
+    pub fn max_value() -> u32 {
+        MODULUS - 1
+    }
+
+    pub fn normalize(p: f32) -> u32 {
+        (p * MODULUS as f32).floor() as u32
+    }
+
+    pub fn gen(&mut self) -> u32 {
+        self.last = (self.last * MULTIPLIER + ADDITIVE) % MODULUS;
         self.last
     }
+
+    // This allows us to fast-forward the RNG,
+    // allowing us to run it in parallel.
+    pub fn future(&self, n: u32) -> Rng {
+        let a = MULTIPLIER as u64;
+        let b = ADDITIVE as u64;
+        let m = MODULUS as u64;
+
+        //                          (a^n - 1) mod (a-1) m
+        // x_k = ((a^n x_0 mod m) + --------------------- b) mod m
+        //                                   a - 1
+        //
+        // Since (a - 1) divides (a^n - 1) mod (a-1) m,
+        // the subtraction does not overflow and thus can be non-modular.
+        //
+        let new_seed =
+            (powmod(a, n, m) * self.last as u64) % m +
+            (powmod(a, n, (a-1) * m) - 1) / (a-1) * b;
+
+        Rng { last: (new_seed % m) as u32 }
+    }
 }
 
-struct AAGen<'a> {
-    rng: &'a mut MyRandom,
-    data: Vec<(u32, u8)>
+
+// This will end up keeping track of threads, like
+// in the other multithreaded Rust version, in
+// order to keep writes in order.
+//
+// This is stolen from another multithreaded Rust
+// implementation, although that implementation
+// was not able to parallelize the RNG itself.
+struct BlockSubmitter<W: io::Write> {
+    writer: W,
+    pub waiting_on: usize,
 }
-impl<'a> AAGen<'a> {
-    fn new<'b>(rng: &'b mut MyRandom, aa: &[(char, f32)]) -> AAGen<'b> {
-        let mut cum = 0.;
-        let data = aa.iter()
-            .map(|&(ch, p)| { cum += p; (MyRandom::normalize(cum), ch as u8) })
-            .collect();
-        AAGen { rng: rng, data: data }
+
+impl<W: io::Write> BlockSubmitter<W> {
+    fn submit(&mut self, data: &[u8], block_num: usize) -> Option<io::Result<()>> {
+        if block_num == self.waiting_on {
+            self.waiting_on += 1;
+            Some(self.submit_async(data))
+        }
+        else {
+            None
+        }
     }
-}
-impl<'a> Iterator for AAGen<'a> {
-    type Item = u8;
-
-    fn next(&mut self) -> Option<u8> {
-        let r = self.rng.gen();
-        self.data.iter()
-            .skip_while(|pc| pc.0 < r)
-            .map(|&(_, c)| c)
-            .next()
+
+    fn submit_async(&mut self, data: &[u8]) -> io::Result<()> {
+        self.writer.write_all(data)
     }
 }
 
-fn make_fasta<W: Write, I: Iterator<Item=u8>>(
-    wr: &mut W, header: &str, mut it: I, mut n: usize)
-    -> io::Result<()>
+
+// For repeating strings as output
+fn fasta_static<W: io::Write>(
+    writer: &mut W,
+    header: &[u8],
+    data: &[u8],
+    mut n: usize
+) -> io::Result<()>
 {
-    try!(wr.write(header.as_bytes()));
-    let mut line = [0; LINE_LENGTH + 1];
+    // The aim here is to print a short(ish) string cyclically
+    // with line breaks as appropriate.
+    //
+    // The secret technique is to repeat the string such that
+    // any wanted line is a single offset in the string.
+    //
+    // This technique is stolen from the Haskell version.
+
+    try!(writer.write_all(header));
+
+    // Maximum offset is data.len(),
+    // Maximum read len is LINE_LEN
+    let stream = data.iter().cloned().cycle();
+    let mut extended: Vec<u8> = stream.take(data.len() + LINE_LEN + 1).collect();
+
+    let mut offset = 0;
     while n > 0 {
-        let nb = min(LINE_LENGTH, n);
-        for i in 0..nb {
-            line[i] = it.next().unwrap();
+        let write_len = min(LINE_LEN, n);
+        let end = offset + write_len;
+        n -= write_len;
+
+        let tmp = extended[end];
+        extended[end] = b'\n';
+        try!(writer.write_all(&extended[offset..end + 1]));
+        extended[end] = tmp;
+
+        offset = end;
+        offset %= data.len();
+    }
+
+    Ok(())
+}
+
+
+// For RNG streams as output
+fn fasta<W: io::Write + Send + 'static>(
+    submitter: &Arc<Mutex<BlockSubmitter<W>>>,
+    header: &[u8],
+    table: &[(u8, f32)],
+    rng: &mut Rng,
+    n: usize
+) -> io::Result<()>
+{
+    // There's another secret technique in use here:
+    // we generate a lookup table to cache search of the
+    // aa buffer.
+    //
+    // The secret technique used is stolen from Haskell's
+    // implementation, and is the main secret to the Haskell
+    // implementation's  speed.
+    fn gen_lookup_table(aa: &[(u8, f32)]) -> Vec<u8> {
+        let mut table = Vec::with_capacity(Rng::max_value() as usize + 1);
+
+        let mut cumulative_prob = 0.0;
+        let mut cumulative_norm = 0;
+
+        for &(byte, prob) in aa {
+            let last_norm = cumulative_norm;
+            cumulative_prob += prob;
+            cumulative_norm = min(Rng::max_value(), Rng::normalize(cumulative_prob)) + 1;
+
+            table.extend((0..cumulative_norm - last_norm).map(|_| byte));
         }
-        n -= nb;
-        line[nb] = '\n' as u8;
-        try!(wr.write(&line[..nb+1]));
+
+        table
+    }
+
+    {
+        try!(submitter.lock().unwrap().submit_async(header));
     }
+
+    let lookup_table = Arc::new(gen_lookup_table(table));
+
+    let thread_count = 4; // avoid external dependency
+    let mut threads = Vec::new();
+    for block_num in (0..thread_count) {
+        let offset = BLOCK_THOROUGHPUT * block_num;
+
+        let local_submitter = submitter.clone();
+        let local_lookup_table = lookup_table.clone();
+        let local_rng = rng.future(offset as u32);
+
+        threads.push(thread::spawn(move || {
+            gen_block(
+                local_submitter,
+                local_lookup_table,
+                local_rng,
+                n.saturating_sub(offset),
+                block_num,
+                thread_count
+            )
+        }));
+    }
+
+    for thread in threads {
+        try!(thread.join().unwrap());
+    }
+
+    *rng = rng.future(n as u32);
+
     Ok(())
 }
 
-fn run<W: Write>(writer: &mut W) -> io::Result<()> {
-    let mut args = env::args();
-    let n = if env::var_os("RUST_BENCH").is_some() {
-        25000000
-    } else if args.len() <= 1 {
-        1000
-    } else {
-        args.nth(1).unwrap().parse().unwrap()
-    };
-
-    let rng = &mut MyRandom::new();
-    let alu =
-        "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG\
-        GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA\
-        CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT\
-        ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA\
-        GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG\
-        AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC\
-        AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
-    let iub = &[('a', 0.27), ('c', 0.12), ('g', 0.12),
-                ('t', 0.27), ('B', 0.02), ('D', 0.02),
-                ('H', 0.02), ('K', 0.02), ('M', 0.02),
-                ('N', 0.02), ('R', 0.02), ('S', 0.02),
-                ('V', 0.02), ('W', 0.02), ('Y', 0.02)];
-    let homosapiens = &[('a', 0.3029549426680),
-                        ('c', 0.1979883004921),
-                        ('g', 0.1975473066391),
-                        ('t', 0.3015094502008)];
-
-    try!(make_fasta(writer, ">ONE Homo sapiens alu\n",
-                    alu.as_bytes().iter().cycle().cloned(), n * 2));
-    try!(make_fasta(writer, ">TWO IUB ambiguity codes\n",
-                    AAGen::new(rng, iub), n * 3));
-    try!(make_fasta(writer, ">THREE Homo sapiens frequency\n",
-                    AAGen::new(rng, homosapiens), n * 5));
-
-    writer.flush()
+// A very optimized writer.
+// I have a feeling a simpler version wouldn't slow
+// things down too much, though, since the RNG
+// is the really heavy hitter.
+fn gen_block<W: io::Write>(
+    submitter: Arc<Mutex<BlockSubmitter<W>>>,
+    lookup_table: Arc<Vec<u8>>,
+    mut rng: Rng,
+    mut length: usize,
+    mut block_num: usize,
+    block_stride: usize,
+) -> io::Result<()>
+{
+    // Include newlines in block
+    length += length / LINE_LEN;
+    let block: &mut [u8] = &mut [b'\n'; BLOCK_LEN];
+
+    while length > 0 {
+        {
+            let gen_into = &mut block[..min(length, BLOCK_LEN)];
+
+            // Write random numbers, skipping newlines
+            for (i, byte) in gen_into.iter_mut().enumerate() {
+                if (i + 1) % (LINE_LEN + 1) != 0 {
+                    *byte = lookup_table[rng.gen() as usize];
+                }
+            }
+        }
+
+        let write_out = {
+            if length >= BLOCK_LEN               { &mut *block }
+            else if length % (LINE_LEN + 1) == 0 { &mut block[..length] }
+            else                                 { &mut block[..length + 1] }
+        };
+
+        *write_out.last_mut().unwrap() = b'\n';
+        loop {
+            match submitter.lock().unwrap().submit(write_out, block_num) {
+                Some(result) => { try!(result); break; }
+                None => std::thread::yield_now()
+            }
+        }
+        block_num += block_stride;
+        rng = rng.future((BLOCK_THOROUGHPUT * (block_stride - 1)) as u32);
+        length = length.saturating_sub(BLOCK_LEN * (block_stride - 1));
+
+        length = length.saturating_sub(BLOCK_LEN);
+    }
+
+    Ok(())
 }
 
+
+fn run<W: io::Write + Send + 'static>(writer: W) -> io::Result<()> {
+    let n = std::env::args_os().nth(1)
+        .and_then(|s| s.into_string().ok())
+        .and_then(|n| n.parse().ok())
+        .unwrap_or(1000);
+
+    let rng = &mut Rng::new();
+
+    // Use automatic buffering for the static version...
+    let mut writer = io::BufWriter::with_capacity(STDIN_BUF, writer);
+    try!(fasta_static(&mut writer, b">ONE Homo sapiens alu\n", ALU, n * 2));
+
+    // ...but the dynamic version does its own buffering already
+    let writer = try!(writer.into_inner());
+    let submitter = Arc::new(Mutex::new(BlockSubmitter { writer: writer, waiting_on: 0 }));
+
+    { submitter.lock().unwrap().waiting_on = 0; }
+    try!(fasta(&submitter, b">TWO IUB ambiguity codes\n", &IUB, rng, n * 3));
+    { submitter.lock().unwrap().waiting_on = 0; }
+    try!(fasta(&submitter, b">THREE Homo sapiens frequency\n", &HOMOSAPIENS, rng, n * 5));
+
+    Ok(())
+}
+
+
 fn main() {
-    let res = if env::var_os("RUST_BENCH").is_some() {
-        let mut file = BufWriter::new(File::create("./shootout-fasta.data").unwrap());
-        run(&mut file)
-    } else {
-        run(&mut io::stdout())
-    };
-    res.unwrap()
+    run(io::stdout()).unwrap()
 }
index 232d6b414f580cb4b973388793e13a5551ee94da..21ac23253c86a7d16ac5a0e2ee21408638bfd2c9 100644 (file)
@@ -192,7 +192,7 @@ fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec<u8>) {
             i += 2;
         }
 
-        res.push(cur_byte^-1);
+        res.push(cur_byte^!0);
     }
 }
 
index 5ba678ce183dd14cd8a3463dbcfb02321b33bba5..1a9ea8bff08b3ea99d5f6244bbde5a8614d61ec6 100644 (file)
 // OF THE POSSIBILITY OF SUCH DAMAGE.
 
 use std::mem;
+use std::ops::{Add, Sub, Mul};
 
 const PI: f64 = 3.141592653589793;
 const SOLAR_MASS: f64 = 4.0 * PI * PI;
 const YEAR: f64 = 365.24;
 const N_BODIES: usize = 5;
+const N_PAIRS: usize = N_BODIES * (N_BODIES - 1) / 2;
 
-static BODIES: [Planet;N_BODIES] = [
+const BODIES: [Planet; N_BODIES] = [
     // Sun
     Planet {
-        x: 0.0, y: 0.0, z: 0.0,
-        vx: 0.0, vy: 0.0, vz: 0.0,
+        pos: Vec3(0.0, 0.0, 0.0),
+        vel: Vec3(0.0, 0.0, 0.0),
         mass: SOLAR_MASS,
     },
     // Jupiter
     Planet {
-        x: 4.84143144246472090e+00,
-        y: -1.16032004402742839e+00,
-        z: -1.03622044471123109e-01,
-        vx: 1.66007664274403694e-03 * YEAR,
-        vy: 7.69901118419740425e-03 * YEAR,
-        vz: -6.90460016972063023e-05 * YEAR,
+        pos: Vec3(4.84143144246472090e+00,
+                  -1.16032004402742839e+00,
+                  -1.03622044471123109e-01),
+        vel: Vec3(1.66007664274403694e-03 * YEAR,
+                  7.69901118419740425e-03 * YEAR,
+                  -6.90460016972063023e-05 * YEAR),
         mass: 9.54791938424326609e-04 * SOLAR_MASS,
     },
     // Saturn
     Planet {
-        x: 8.34336671824457987e+00,
-        y: 4.12479856412430479e+00,
-        z: -4.03523417114321381e-01,
-        vx: -2.76742510726862411e-03 * YEAR,
-        vy: 4.99852801234917238e-03 * YEAR,
-        vz: 2.30417297573763929e-05 * YEAR,
+        pos: Vec3(8.34336671824457987e+00,
+                  4.12479856412430479e+00,
+                  -4.03523417114321381e-01),
+        vel: Vec3(-2.76742510726862411e-03 * YEAR,
+                  4.99852801234917238e-03 * YEAR,
+                  2.30417297573763929e-05 * YEAR),
         mass: 2.85885980666130812e-04 * SOLAR_MASS,
     },
     // Uranus
     Planet {
-        x: 1.28943695621391310e+01,
-        y: -1.51111514016986312e+01,
-        z: -2.23307578892655734e-01,
-        vx: 2.96460137564761618e-03 * YEAR,
-        vy: 2.37847173959480950e-03 * YEAR,
-        vz: -2.96589568540237556e-05 * YEAR,
+        pos: Vec3(1.28943695621391310e+01,
+                  -1.51111514016986312e+01,
+                  -2.23307578892655734e-01),
+        vel: Vec3(2.96460137564761618e-03 * YEAR,
+                  2.37847173959480950e-03 * YEAR,
+                  -2.96589568540237556e-05 * YEAR),
         mass: 4.36624404335156298e-05 * SOLAR_MASS,
     },
     // Neptune
     Planet {
-        x: 1.53796971148509165e+01,
-        y: -2.59193146099879641e+01,
-        z: 1.79258772950371181e-01,
-        vx: 2.68067772490389322e-03 * YEAR,
-        vy: 1.62824170038242295e-03 * YEAR,
-        vz: -9.51592254519715870e-05 * YEAR,
+        pos: Vec3(1.53796971148509165e+01,
+                  -2.59193146099879641e+01,
+                  1.79258772950371181e-01),
+        vel: Vec3(2.68067772490389322e-03 * YEAR,
+                  1.62824170038242295e-03 * YEAR,
+                  -9.51592254519715870e-05 * YEAR),
         mass: 5.15138902046611451e-05 * SOLAR_MASS,
     },
 ];
 
-#[derive(Copy, Clone)]
+/// A 3d Vector type with oveloaded operators to improve readability.
+#[derive(Clone, Copy)]
+struct Vec3(pub f64, pub f64, pub f64);
+
+impl Vec3 {
+    fn zero() -> Self { Vec3(0.0, 0.0, 0.0) }
+
+    fn norm(&self) -> f64 { self.squared_norm().sqrt() }
+
+    fn squared_norm(&self) -> f64 {
+        self.0 * self.0 + self.1 * self.1 + self.2 * self.2
+    }
+}
+
+impl Add for Vec3 {
+    type Output = Self;
+    fn add(self, rhs: Self) -> Self {
+        Vec3(self.0 + rhs.0, self.1 + rhs.1, self.2 + rhs.2)
+    }
+}
+
+impl Sub for Vec3 {
+    type Output = Self;
+    fn sub(self, rhs: Self) -> Self {
+        Vec3(self.0 - rhs.0, self.1 - rhs.1, self.2 - rhs.2)
+    }
+}
+
+impl Mul<f64> for Vec3 {
+    type Output = Self;
+    fn mul(self, rhs: f64) -> Self {
+        Vec3(self.0 * rhs, self.1 * rhs, self.2 * rhs)
+    }
+}
+
+#[derive(Clone, Copy)]
 struct Planet {
-    x: f64, y: f64, z: f64,
-    vx: f64, vy: f64, vz: f64,
+    pos: Vec3,
+    vel: Vec3,
     mass: f64,
 }
 
-fn advance(bodies: &mut [Planet;N_BODIES], dt: f64, steps: isize) {
-    for _ in 0..steps {
-        let mut b_slice: &mut [_] = bodies;
-        loop {
-            let bi = match shift_mut_ref(&mut b_slice) {
-                Some(bi) => bi,
-                None => break
-            };
-            for bj in &mut *b_slice {
-                let dx = bi.x - bj.x;
-                let dy = bi.y - bj.y;
-                let dz = bi.z - bj.z;
-
-                let d2 = dx * dx + dy * dy + dz * dz;
-                let mag = dt / (d2 * d2.sqrt());
-
-                let massj_mag = bj.mass * mag;
-                bi.vx -= dx * massj_mag;
-                bi.vy -= dy * massj_mag;
-                bi.vz -= dz * massj_mag;
-
-                let massi_mag = bi.mass * mag;
-                bj.vx += dx * massi_mag;
-                bj.vy += dy * massi_mag;
-                bj.vz += dz * massi_mag;
-            }
-            bi.x += dt * bi.vx;
-            bi.y += dt * bi.vy;
-            bi.z += dt * bi.vz;
+/// Computes all pairwise position differences between the planets.
+fn pairwise_diffs(bodies: &[Planet; N_BODIES], diff: &mut [Vec3; N_PAIRS]) {
+    let mut bodies = bodies.iter();
+    let mut diff = diff.iter_mut();
+    while let Some(bi) = bodies.next() {
+        for bj in bodies.clone() {
+            *diff.next().unwrap() = bi.pos - bj.pos;
+        }
+    }
+}
+
+/// Computes the magnitude of the force between each pair of planets.
+fn magnitudes(diff: &[Vec3; N_PAIRS], dt: f64, mag: &mut [f64; N_PAIRS]) {
+    for (mag, diff) in mag.iter_mut().zip(diff.iter()) {
+        let d2 = diff.squared_norm();
+        *mag = dt / (d2 * d2.sqrt());
+    }
+}
+
+/// Updates the velocities of the planets by computing their gravitational
+/// accelerations and performing one step of Euler integration.
+fn update_velocities(bodies: &mut [Planet; N_BODIES], dt: f64,
+                     diff: &mut [Vec3; N_PAIRS], mag: &mut [f64; N_PAIRS]) {
+    pairwise_diffs(bodies, diff);
+    magnitudes(&diff, dt, mag);
+
+    let mut bodies = &mut bodies[..];
+    let mut mag = mag.iter();
+    let mut diff = diff.iter();
+    while let Some(bi) = shift_mut_ref(&mut bodies) {
+        for bj in bodies.iter_mut() {
+            let diff = *diff.next().unwrap();
+            let mag = *mag.next().unwrap();
+            bi.vel = bi.vel - diff * (bj.mass * mag);
+            bj.vel = bj.vel + diff * (bi.mass * mag);
         }
     }
 }
 
-fn energy(bodies: &[Planet;N_BODIES]) -> f64 {
+/// Advances the solar system by one timestep by first updating the
+/// velocities and then integrating the positions using the updated velocities.
+///
+/// Note: the `diff` & `mag` arrays are effectively scratch space. They're
+/// provided as arguments to avoid re-zeroing them every time `advance` is
+/// called.
+fn advance(mut bodies: &mut [Planet; N_BODIES], dt: f64,
+           diff: &mut [Vec3; N_PAIRS], mag: &mut [f64; N_PAIRS]) {
+    update_velocities(bodies, dt, diff, mag);
+    for body in bodies.iter_mut() {
+        body.pos = body.pos + body.vel * dt;
+    }
+}
+
+/// Computes the total energy of the solar system.
+fn energy(bodies: &[Planet; N_BODIES]) -> f64 {
     let mut e = 0.0;
     let mut bodies = bodies.iter();
-    loop {
-        let bi = match bodies.next() {
-            Some(bi) => bi,
-            None => break
-        };
-        e += (bi.vx * bi.vx + bi.vy * bi.vy + bi.vz * bi.vz) * bi.mass / 2.0;
-        for bj in bodies.clone() {
-            let dx = bi.x - bj.x;
-            let dy = bi.y - bj.y;
-            let dz = bi.z - bj.z;
-            let dist = (dx * dx + dy * dy + dz * dz).sqrt();
-            e -= bi.mass * bj.mass / dist;
-        }
+    while let Some(bi) = bodies.next() {
+        e += bi.vel.squared_norm() * bi.mass / 2.0
+           - bi.mass * bodies.clone()
+                             .map(|bj| bj.mass / (bi.pos - bj.pos).norm())
+                             .fold(0.0, |a, b| a + b);
     }
     e
 }
 
-fn offset_momentum(bodies: &mut [Planet;N_BODIES]) {
-    let mut px = 0.0;
-    let mut py = 0.0;
-    let mut pz = 0.0;
-    for bi in bodies.iter() {
-        px += bi.vx * bi.mass;
-        py += bi.vy * bi.mass;
-        pz += bi.vz * bi.mass;
-    }
-    let sun = &mut bodies[0];
-    sun.vx = - px / SOLAR_MASS;
-    sun.vy = - py / SOLAR_MASS;
-    sun.vz = - pz / SOLAR_MASS;
+/// Offsets the sun's velocity to make the overall momentum of the system zero.
+fn offset_momentum(bodies: &mut [Planet; N_BODIES]) {
+    let p = bodies.iter().fold(Vec3::zero(), |v, b| v + b.vel * b.mass);
+    bodies[0].vel = p * (-1.0 / bodies[0].mass);
 }
 
 fn main() {
@@ -178,11 +219,15 @@ fn main() {
             .unwrap_or(1000)
     };
     let mut bodies = BODIES;
+    let mut diff = [Vec3::zero(); N_PAIRS];
+    let mut mag = [0.0f64; N_PAIRS];
 
     offset_momentum(&mut bodies);
     println!("{:.9}", energy(&bodies));
 
-    advance(&mut bodies, 0.01, n);
+    for _ in 0..n {
+        advance(&mut bodies, 0.01, &mut diff, &mut mag);
+    }
 
     println!("{:.9}", energy(&bodies));
 }
diff --git a/src/test/borrowck-loan-of-static-data-issue-27616.rs b/src/test/borrowck-loan-of-static-data-issue-27616.rs
deleted file mode 100644 (file)
index 228e710..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::mem;
-
-fn leak<T>(mut b: Box<T>) -> &'static mut T {
-    // isn't this supposed to be safe?
-    let inner = &mut *b as *mut _;
-    mem::forget(b);
-    unsafe { &mut *inner }
-}
-
-fn evil(mut s: &'static mut String)
-{
-    // create alias
-    let alias: &'static mut String = s;
-    let inner: &str = &alias;
-    // free value
-    *s = String::new(); //~ ERROR cannot assign
-    let _spray = "0wned".to_owned();
-    // ... and then use it
-    println!("{}", inner);
-}
-
-fn main() {
-    evil(leak(Box::new("hello".to_owned())));
-}
diff --git a/src/test/codegen/adjustments.rs b/src/test/codegen/adjustments.rs
new file mode 100644 (file)
index 0000000..a61fa84
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+// Hack to get the correct size for the length part in slices
+// CHECK: @helper([[USIZE:i[0-9]+]])
+#[no_mangle]
+fn helper(_: usize) {
+}
+
+// CHECK-LABEL: @no_op_slice_adjustment
+#[no_mangle]
+pub fn no_op_slice_adjustment(x: &[u8]) -> &[u8] {
+    // We used to generate an extra alloca and memcpy for the block's trailing expression value, so
+    // check that we copy directly to the return value slot
+// CHECK: [[SRC:%[0-9]+]] = bitcast { i8*, [[USIZE]] }* %x to
+// CHECK: [[DST:%[0-9]+]] = bitcast { i8*, [[USIZE]] }* %sret_slot to i8*
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* [[DST]], i8* [[SRC]],
+    { x }
+}
+
+// CHECK-LABEL: @no_op_slice_adjustment2
+#[no_mangle]
+pub fn no_op_slice_adjustment2(x: &[u8]) -> &[u8] {
+    // We used to generate an extra alloca and memcpy for the function's return value, so check
+    // that there's no memcpy (the slice is written to sret_slot element-wise)
+// CHECK-NOT: call void @llvm.memcpy.
+    no_op_slice_adjustment(x)
+}
index 2a136d7024d9b7fcf54a320f12f4c8d85cc5b79f..c8c9f5b407c421b11458d6b6c514f54ac64afbaf 100644 (file)
@@ -10,6 +10,8 @@
 
 // compile-flags: -C no-prepopulate-passes
 
+#![crate_type = "lib"]
+
 static X: i32 = 5;
 
 // CHECK-LABEL: @raw_ptr_to_raw_ptr_noop
diff --git a/src/test/codegen/consts.rs b/src/test/codegen/consts.rs
new file mode 100644 (file)
index 0000000..6b4e626
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+// Below, these constants are defined as enum variants that by itself would
+// have a lower alignment than the enum type. Ensure that we mark them
+// correctly with the higher alignment of the enum.
+
+// CHECK: @STATIC = {{.*}}, align 4
+
+// This checks the constants from inline_enum_const
+// CHECK: @const{{[0-9]+}} = {{.*}}, align 2
+
+// This checks the constants from {low,high}_align_const, they share the same
+// constant, but the alignment differs, so the higher one should be used
+// CHECK: @const{{[0-9]+}} = {{.*}}, align 4
+
+#[derive(Copy, Clone)]
+
+// repr(i16) is required for the {low,high}_align_const test
+#[repr(i16)]
+pub enum E<A, B> {
+    A(A),
+    B(B),
+}
+
+#[no_mangle]
+pub static STATIC: E<i16, i32> = E::A(0);
+
+// CHECK-LABEL: @static_enum_const
+#[no_mangle]
+pub fn static_enum_const() -> E<i16, i32> {
+   STATIC
+}
+
+// CHECK-LABEL: @inline_enum_const
+#[no_mangle]
+pub fn inline_enum_const() -> E<i8, i16> {
+    E::A(0)
+}
+
+// CHECK-LABEL: @low_align_const
+#[no_mangle]
+pub fn low_align_const() -> E<i16, [i16; 3]> {
+// Check that low_align_const and high_align_const use the same constant
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{[0-9]+}}, i8* {{.*}} [[LOW_HIGH:@const[0-9]+]]
+    E::A(0)
+}
+
+// CHECK-LABEL: @high_align_const
+#[no_mangle]
+pub fn high_align_const() -> E<i16, i32> {
+// Check that low_align_const and high_align_const use the same constant
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{[0-9]}}, i8* {{.*}} [[LOW_HIGH]]
+    E::A(0)
+}
index 4c30b5ce02f4d1af3e1b9f37ba78dc1b516c9693..ff9d54e67e4782439005eb7d2dcc048b658209b7 100644 (file)
@@ -10,6 +10,7 @@
 
 // compile-flags: -C no-prepopulate-passes
 
+#![crate_type = "lib"]
 #![feature(unwind_attributes)]
 
 extern {
index 7706c97380b166192b8543ab6075c261342ab1b8..90ced88324e7fb1041e1f7e3ef3d34ab778c560b 100644 (file)
@@ -10,6 +10,7 @@
 
 // compile-flags: -C no-prepopulate-passes
 
+#![crate_type = "lib"]
 #![feature(allocator)]
 
 pub struct S {
diff --git a/src/test/codegen/gdb_debug_script_load.rs b/src/test/codegen/gdb_debug_script_load.rs
new file mode 100644 (file)
index 0000000..efaca29
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-tidy-linelength
+// ignore-windows
+// ignore-macos
+
+// compile-flags: -g -C no-prepopulate-passes
+
+#![feature(start)]
+
+// CHECK-LABEL: @main
+// CHECK: load volatile i8, i8* getelementptr inbounds ([[B:\[[0-9]* x i8\]]], [[B]]* @__rustc_debug_gdb_scripts_section__, i32 0, i32 0), align 1
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    return 0;
+}
index 99b43552b0de4ed8325162742e94cf1f40bde6e1..5ad3854c05ccc4a1e201a2c995972225bb8bad95 100644 (file)
@@ -10,6 +10,8 @@
 
 // compile-flags: -C no-prepopulate-passes
 
+#![crate_type = "lib"]
+
 // CHECK: @VAR1 = constant i32 1, section ".test_one"
 #[no_mangle]
 #[link_section = ".test_one"]
index b51da69fef2251a4f80b99763e2f160e71d79cb6..21f23b6ea18612dee9c0ae2708964553a47f3639 100644 (file)
@@ -10,6 +10,8 @@
 
 // compile-flags: -C no-prepopulate-passes
 
+#![crate_type = "lib"]
+
 pub struct Bytes {
   a: u8,
   b: u8,
diff --git a/src/test/codegen/match.rs b/src/test/codegen/match.rs
new file mode 100644 (file)
index 0000000..ac47f60
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+pub enum E {
+    A,
+    B,
+}
+
+// CHECK-LABEL: @exhaustive_match
+#[no_mangle]
+pub fn exhaustive_match(e: E) {
+// CHECK: switch{{.*}}, label %[[DEFAULT:[a-zA-Z0-9_]+]]
+// CHECK: [[DEFAULT]]:
+// CHECK-NEXT: unreachable
+    match e {
+        E::A => (),
+        E::B => (),
+    }
+}
diff --git a/src/test/codegen/refs.rs b/src/test/codegen/refs.rs
new file mode 100644 (file)
index 0000000..08eec00
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+// Hack to get the correct size for the length part in slices
+// CHECK: @helper([[USIZE:i[0-9]+]])
+#[no_mangle]
+fn helper(_: usize) {
+}
+
+// CHECK-LABEL: @ref_dst
+#[no_mangle]
+pub fn ref_dst(s: &[u8]) {
+    // We used to generate an extra alloca and memcpy to ref the dst, so check that we copy
+    // directly to the alloca for "x"
+// CHECK: [[SRC:%[0-9]+]] = bitcast { i8*, [[USIZE]] }* %s to i8*
+// CHECK: [[DST:%[0-9]+]] = bitcast { i8*, [[USIZE]] }* %x to i8*
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* [[DST]], i8* [[SRC]],
+    let x = &*s;
+}
index 72862ea8b6ff912fa7551e780d01b2aff38b498b..5d2d47e1bf3f6f3ed53b375448667fa41d49449b 100644 (file)
@@ -10,6 +10,8 @@
 
 // compile-flags: -C no-prepopulate-passes
 
+#![crate_type = "lib"]
+
 pub struct Bytes {
   a: u8,
   b: u8,
index fef27af59571b186748d84cc7aed01b6d41b5d48..5b24c6bd79f96e75a4666054d35232886241a4a3 100644 (file)
@@ -13,5 +13,5 @@ struct Foo;
 fn main() {
   let mut a = Foo;
   let ref b = Foo;
-  a += *b; //~ Error: binary assignment operation `+=` cannot be applied to types `Foo` and `Foo`
+  a += *b; //~ Error: binary assignment operation `+=` cannot be applied to type `Foo`
 }
index b6c4d59c8488299d859beb46d72f50da458e35f4..d48cff405a6371d473dfafb195d95016c9f43528 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test that we report an error if the trait ref in an qualified type
+// Test that we report an error if the trait ref in a qualified type
 // uses invalid type arguments.
 
 trait Foo<T> {
diff --git a/src/test/compile-fail/attr-usage-inline.rs b/src/test/compile-fail/attr-usage-inline.rs
new file mode 100644 (file)
index 0000000..c6b9b01
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(dead_code)]
+
+#[inline]
+fn f() {}
+
+#[inline] //~ ERROR: attribute should be applied to function
+struct S;
+
+fn main() {}
diff --git a/src/test/compile-fail/attr-usage-repr.rs b/src/test/compile-fail/attr-usage-repr.rs
new file mode 100644 (file)
index 0000000..9bad6a8
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(dead_code)]
+#![feature(repr_simd)]
+
+#[repr(C)] //~ ERROR: attribute should be applied to struct or enum
+fn f() {}
+
+#[repr(C)]
+struct SExtern(f64, f64);
+
+#[repr(packed)]
+struct SPacked(f64, f64);
+
+#[repr(simd)]
+struct SSimd(f64, f64);
+
+#[repr(i8)] //~ ERROR: attribute should be applied to enum
+struct SInt(f64, f64);
+
+#[repr(C)]
+enum EExtern { A, B }
+
+#[repr(packed)] //~ ERROR: attribute should be applied to struct
+enum EPacked { A, B }
+
+#[repr(simd)] //~ ERROR: attribute should be applied to struct
+enum ESimd { A, B }
+
+#[repr(i8)]
+enum EInt { A, B }
+
+fn main() {}
diff --git a/src/test/compile-fail/augmented-assignments-feature-gate-cross.rs b/src/test/compile-fail/augmented-assignments-feature-gate-cross.rs
new file mode 100644 (file)
index 0000000..c26d6cf
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:augmented_assignments.rs
+
+// Test that the feature gate is needed when using augmented assignments that were overloaded in
+// another crate
+
+extern crate augmented_assignments;
+
+use augmented_assignments::Int;
+
+fn main() {
+    let mut x = Int(0);
+    x += 1;
+    //~^ error: overloaded augmented assignments are not stable
+    // | help: add #![feature(augmented_assignments)] to the crate root to enable
+}
diff --git a/src/test/compile-fail/augmented-assignments-feature-gate.rs b/src/test/compile-fail/augmented-assignments-feature-gate.rs
new file mode 100644 (file)
index 0000000..0db8f98
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::ops::AddAssign;
+
+struct Int(i32);
+
+impl AddAssign<i32> for Int {
+    fn add_assign(&mut self, _: i32) {
+        unimplemented!()
+    }
+}
+
+fn main() {
+    let mut x = Int(0);
+    x += 1;
+    //~^ error: overloaded augmented assignments are not stable
+    // | help: add #![feature(augmented_assignments)] to the crate root to enable
+}
diff --git a/src/test/compile-fail/augmented-assignments-trait.rs b/src/test/compile-fail/augmented-assignments-trait.rs
new file mode 100644 (file)
index 0000000..83e8d1f
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::ops::AddAssign;
+//~^ error: use of unstable library feature 'op_assign_traits'
+
+struct Int(i32);
+
+impl AddAssign for Int {
+    //~^ error: use of unstable library feature 'op_assign_traits'
+    fn add_assign(&mut self, _: Int) {
+        //~^ error: use of unstable library feature 'op_assign_traits'
+        unimplemented!()
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/augmented-assignments.rs b/src/test/compile-fail/augmented-assignments.rs
new file mode 100644 (file)
index 0000000..ee64171
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(augmented_assignments)]
+
+use std::ops::AddAssign;
+
+struct Int(i32);
+
+impl AddAssign for Int {
+    fn add_assign(&mut self, _: Int) {
+        unimplemented!()
+    }
+}
+
+fn main() {
+    let mut x = Int(1);
+    x   //~ error: use of moved value: `x`
+    +=
+    x;  //~ note: `x` moved here because it has type `Int`, which is non-copyable
+
+    let y = Int(2);
+    y   //~ error: cannot borrow immutable local variable `y` as mutable
+    +=
+    Int(1);
+}
index 2c5749e0d5d39ae81127625caa1a3a79b4e7cddf..0d666a4920038aa40254183d496ccf73c9a72af6 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(unknown_features)]
 #![feature(box_syntax)]
 
 struct clam {
index b1abbad525356a5ff43f6a894b765ff3d5a20290..f3417fafe90375ed9996d8b917d90137e123a375 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(unknown_features)]
 #![feature(box_syntax)]
 
 struct Foo(Box<isize>, isize);
diff --git a/src/test/compile-fail/borrowck-argument.rs b/src/test/compile-fail/borrowck-argument.rs
new file mode 100644 (file)
index 0000000..3230689
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[derive(Copy, Clone)]
+struct S;
+
+impl S {
+    fn mutate(&mut self) {
+    }
+}
+
+fn func(arg: S) {
+    arg.mutate(); //~ ERROR: cannot borrow immutable argument
+}
+
+impl S {
+    fn method(&self, arg: S) {
+        arg.mutate(); //~ ERROR: cannot borrow immutable argument
+    }
+}
+
+trait T {
+    fn default(&self, arg: S) {
+        arg.mutate(); //~ ERROR: cannot borrow immutable argument
+    }
+}
+
+impl T for S {}
+
+fn main() {
+    let s = S;
+    func(s);
+    s.method(s);
+    s.default(s);
+    (|arg: S| { arg.mutate() })(s); //~ ERROR: cannot borrow immutable argument
+}
index dd278faa0dc6a7829dd52b5985dec47b2b0c601e..497b0e63edfc149516456355062e256c767a7a1c 100644 (file)
@@ -111,12 +111,9 @@ fn assign_field4<'a>(x: &'a mut Own<Point>) {
     x.y = 3; //~ ERROR cannot borrow
 }
 
-// FIXME(eddyb) #12825 This shouldn't attempt to call deref_mut.
-/*
 fn deref_imm_method(x: Own<Point>) {
     let __isize = x.get();
 }
-*/
 
 fn deref_mut_method1(x: Own<Point>) {
     x.set(0, 0); //~ ERROR cannot borrow
index 9410181659c1a229a73adf620d88c2863091d913..3646a68f06fd745ed09fb0f41df2a2c971339559 100644 (file)
@@ -43,7 +43,7 @@ fn d(x: &mut isize) {
 }
 
 fn e(x: &mut isize) {
-    let c1 = || x = panic!(); //~ ERROR closure cannot assign to immutable local variable
+    let c1 = || x = panic!(); //~ ERROR closure cannot assign to immutable argument
 }
 
 fn main() {
index a0a6e54e942b0a87a43d6ecd22fa96d6d34cc683..a6ce36a5507f2a79096553bdb795cbdf16a4fb5f 100644 (file)
@@ -23,8 +23,7 @@ fn for_func<F>(_f: F) where F: FnOnce() -> bool { panic!() }
 fn produce<T>() -> T { panic!(); }
 
 fn inc(v: &mut Box<isize>) {
-    *v = box() (**v + 1);
-    //~^ WARN deprecated syntax
+    *v = box (**v + 1);
 }
 
 fn pre_freeze_cond() {
index 9356eeda60503f536b504d05af9553e069d1460d..f09e7ffd7e4b791c4b51472ca9db8013b79e0659 100644 (file)
@@ -22,8 +22,7 @@ fn cond() -> bool { panic!() }
 fn produce<T>() -> T { panic!(); }
 
 fn inc(v: &mut Box<isize>) {
-    *v = box() (**v + 1);
-    //~^ WARN deprecated syntax
+    *v = box (**v + 1);
 }
 
 fn loop_overarching_alias_mut() {
index c3dcddf858724c3f020207ee8d149d175f409a09..1ed779cfaac7153a450d5fab13c4733720877205 100644 (file)
@@ -23,8 +23,7 @@ fn for_func<F>(_f: F) where F: FnOnce() -> bool { panic!() }
 fn produce<T>() -> T { panic!(); }
 
 fn inc(v: &mut Box<isize>) {
-    *v = box() (**v + 1);
-    //~^ WARN deprecated syntax
+    *v = box (**v + 1);
 }
 
 fn pre_freeze() {
index 558475c28d7014192b0c7e73811ba4a34e227992..a9079cfc27d83accd55023ac708d0611bd581022 100644 (file)
@@ -22,8 +22,7 @@ impl Add for foo {
     fn add(self, f: foo) -> foo {
         let foo(box i) = self;
         let foo(box j) = f;
-        foo(box() (i + j))
-        //~^ WARN deprecated syntax
+        foo(box (i + j))
     }
 }
 
diff --git a/src/test/compile-fail/borrowck-loan-of-static-data-issue-27616.rs b/src/test/compile-fail/borrowck-loan-of-static-data-issue-27616.rs
new file mode 100644 (file)
index 0000000..228e710
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::mem;
+
+fn leak<T>(mut b: Box<T>) -> &'static mut T {
+    // isn't this supposed to be safe?
+    let inner = &mut *b as *mut _;
+    mem::forget(b);
+    unsafe { &mut *inner }
+}
+
+fn evil(mut s: &'static mut String)
+{
+    // create alias
+    let alias: &'static mut String = s;
+    let inner: &str = &alias;
+    // free value
+    *s = String::new(); //~ ERROR cannot assign
+    let _spray = "0wned".to_owned();
+    // ... and then use it
+    println!("{}", inner);
+}
+
+fn main() {
+    evil(leak(Box::new("hello".to_owned())));
+}
diff --git a/src/test/compile-fail/borrowck-mut-borrow-linear-errors.rs b/src/test/compile-fail/borrowck-mut-borrow-linear-errors.rs
new file mode 100644 (file)
index 0000000..38e0e27
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test to ensure we only report an error for the first issued loan that
+// conflicts with a new loan, as opposed to every issued loan.  This keeps us
+// down to O(n) errors (for n problem lines), instead of O(n^2) errors.
+
+fn main() {
+    let mut x = 1;
+    let mut addr;
+    loop {
+        match 1 {
+            1 => { addr = &mut x; }
+            //~^ ERROR cannot borrow `x` as mutable more than once at a time
+            2 => { addr = &mut x; }
+            //~^ ERROR cannot borrow `x` as mutable more than once at a time
+            _ => { addr = &mut x; }
+            //~^ ERROR cannot borrow `x` as mutable more than once at a time
+        }
+    }
+}
index 3eca850e493c7231687dddfe6ad84c54235dd696..1c12ca9c1de76234a3e4d72554992b55048d8074 100644 (file)
@@ -17,7 +17,7 @@ fn a<F:Fn(isize, isize) -> isize>(mut f: F) {
 }
 
 fn b<F:FnMut(isize, isize) -> isize>(f: F) {
-    f(1, 2);    //~ ERROR cannot borrow immutable local variable
+    f(1, 2);    //~ ERROR cannot borrow immutable argument
 }
 
 fn c<F:FnOnce(isize, isize) -> isize>(f: F) {
index 92cbbaa1cb442136c89fc8c2fac1d1c378568294..52a4950022d1e13364ae8a26ac5edac2b50e5e8f 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn main() {
-    let u = (5 as bool);
+    let u = 5 as bool;
     //~^ ERROR cannot cast as `bool`
     //~^^ HELP compare with zero instead
 }
diff --git a/src/test/compile-fail/const-err.rs b/src/test/compile-fail/const-err.rs
new file mode 100644 (file)
index 0000000..be67e06
--- /dev/null
@@ -0,0 +1,36 @@
+// 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.
+
+#[allow(exceeding_bitshifts)]
+#[deny(const_err)]
+
+fn black_box<T>(_: T) {
+    unimplemented!()
+}
+
+const BLA: u8 = 200u8 + 200u8;
+//~^ ERROR attempted to add with overflow
+
+fn main() {
+    let a = -std::i8::MIN;
+    //~^ WARN attempted to negate with overflow
+    let b = 200u8 + 200u8 + 200u8;
+    //~^ WARN attempted to add with overflow
+    //~^^ WARN attempted to add with overflow
+    let c = 200u8 * 4;
+    //~^ WARN attempted to mul with overflow
+    let d = 42u8 - (42u8 + 1);
+    //~^ WARN attempted to sub with overflow
+    let _e = BLA;
+    black_box(a);
+    black_box(b);
+    black_box(c);
+    black_box(d);
+}
index f991e5328c1042a72774833e18c06ead1a5e1e1b..daa60955ad88decd4d037bc1fe3299d4d24ec018 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(negate_unsigned)]
-
 #![allow(unused_imports)]
 #![feature(negate_unsigned)]
 
diff --git a/src/test/compile-fail/const-eval-span.rs b/src/test/compile-fail/const-eval-span.rs
new file mode 100644 (file)
index 0000000..3e75afc
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that error in constant evaluation of enum discriminant
+// provides the context for what caused the evaluation.
+
+struct S(i32);
+
+const CONSTANT: S = S(0);
+//~^ ERROR: constant evaluation error: non-constant path in constant expression [E0080]
+
+enum E {
+    V = CONSTANT,
+    //~^ NOTE: for enum discriminant here
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/const-fn-destructuring-arg.rs b/src/test/compile-fail/const-fn-destructuring-arg.rs
new file mode 100644 (file)
index 0000000..1642c04
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// test that certain things are disallowed in const fn signatures
+
+#![feature(const_fn)]
+
+// no destructuring
+const fn i((a, b): (u32, u32)) -> u32 { a + b } //~ ERROR: E0022
+
+fn main() {}
index dd9a415311e534d37ec7acba8c590dafff46bd43..59e0db7b35508c8ca8cd6375604a99b51d3b9f94 100644 (file)
@@ -17,5 +17,5 @@ extern crate const_fn_lib;
 use const_fn_lib::foo;
 
 fn main() {
-    let x: [usize; foo()] = []; //~ ERROR unsupported constant expr
+    let x: [usize; foo()] = []; //~ ERROR non-constant path in constant expr
 }
index cd021a0d3b1cb2e2d1a93b419a71dd92049d659a..786c72b66f36fe812677a781aacf61f9f7a3d85d 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Check that an constant-evaluation underflow highlights the correct
+// Check that a constant-evaluation underflow highlights the correct
 // spot (where the underflow occurred), while also providing the
 // overall context for what caused the evaluation.
 
index a31da114679242b322e65817e77b05afb5ed131d..020717dc1e18f8fbfccefd584da4e2c296e99e6c 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Check that an constant-evaluation underflow highlights the correct
+// Check that a constant-evaluation underflow highlights the correct
 // spot (where the underflow occurred).
 
 const ONE: usize = 1;
diff --git a/src/test/compile-fail/const-slice-oob.rs b/src/test/compile-fail/const-slice-oob.rs
new file mode 100644 (file)
index 0000000..519c491
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const FOO: &'static[u32] = &[1, 2, 3];
+const BAR: u32 = FOO[5]; //~ ERROR const index-expr is out of bounds
+
+fn main() {
+    let _ = BAR;
+}
index 6e9b120aa69b5a6b27a173b69a5ec41cc7535969..e8e37d8804986b60894687371c1fa997363475de 100644 (file)
@@ -23,12 +23,12 @@ struct B(isize);
 
 #[derive(FromPrimitive)]
 enum C { Foo(isize), Bar(usize) }
-//~^^ ERROR `FromPrimitive` cannot be derived for enum variants with arguments
-//~^^^ ERROR `FromPrimitive` cannot be derived for enum variants with arguments
+//~^^ ERROR `FromPrimitive` cannot be derived for enums with non-unit variants
+//~^^^ ERROR `FromPrimitive` cannot be derived for enums with non-unit variants
 
 #[derive(FromPrimitive)]
 enum D { Baz { x: isize } }
-//~^^ ERROR `FromPrimitive` cannot be derived for enums with struct variants
-//~^^^ ERROR `FromPrimitive` cannot be derived for enums with struct variants
+//~^^ ERROR `FromPrimitive` cannot be derived for enums with non-unit variants
+//~^^^ ERROR `FromPrimitive` cannot be derived for enums with non-unit variants
 
 pub fn main() {}
index 19f790ddc90717875b915d866a5bd7670bfe7ae0..9cfeaca6dfadf2a3120577f8accc69dc03f448db 100644 (file)
@@ -19,7 +19,6 @@ use std::cell::Cell;
 use id::Id;
 
 mod s {
-    #![allow(unstable)]
     use std::sync::atomic::{AtomicUsize, Ordering};
 
     static S_COUNT: AtomicUsize = AtomicUsize::new(0);
index 584e5eabf0cd8f7e21cee5de46b9ea11bcfac8e3..d36293a484d4e3cb638ac934da2bb2fe39fd4435 100644 (file)
@@ -16,7 +16,6 @@
 //  which is a reduction of this code to more directly show the reason
 //  for the error message we see here.)
 
-#![allow(unstable)]
 #![feature(const_fn)]
 
 extern crate arena;
@@ -26,7 +25,6 @@ use std::cell::Cell;
 use id::Id;
 
 mod s {
-    #![allow(unstable)]
     use std::sync::atomic::{AtomicUsize, Ordering};
 
     static S_COUNT: AtomicUsize = AtomicUsize::new(0);
index 7a204e6143eeff0556150603406174155f746756..6cbed34c7ad94053179eec6f7959ab9ff55cf226 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Check that a arena (TypedArena) cannot carry elements whose drop
+// Check that an arena (TypedArena) cannot carry elements whose drop
 // methods might access borrowed data of lifetime that does not
 // strictly outlive the arena itself.
 //
@@ -19,8 +19,6 @@
 // (Also compare against dropck_tarena_cycle_checked.rs, from which
 // this was reduced to better understand its error message.)
 
-#![allow(unstable)]
-
 extern crate arena;
 
 use arena::TypedArena;
@@ -32,7 +30,7 @@ struct CheckId<T:HasId> { v: T }
 // In the code below, the impl of HasId for `&'a usize` does not
 // actually access the borrowed data, but the point is that the
 // interface to CheckId does not (and cannot) know that, and therefore
-// when encountering the a value V of type CheckId<S>, we must
+// when encountering a value V of type CheckId<S>, we must
 // conservatively force the type S to strictly outlive V.
 impl<T:HasId> Drop for CheckId<T> {
     fn drop(&mut self) {
index 6e0679da949e1792c3e3881ed0a915175c53511a..e701718028a7a05349d952f07cb98270b091db4e 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // Reject mixing cyclic structure and Drop when using trait
-// objects to hide the the cross-references.
+// objects to hide the cross-references.
 //
 // (Compare against compile-fail/dropck_vec_cycle_checked.rs)
 
index bc33ff8399aa5611fd59cd17c55469a61e0fec16..caf25e68d568ca3af4bd8691822507ca8e1abf06 100644 (file)
@@ -18,7 +18,6 @@ use std::cell::Cell;
 use id::Id;
 
 mod s {
-    #![allow(unstable)]
     use std::sync::atomic::{AtomicUsize, Ordering};
 
     static S_COUNT: AtomicUsize = AtomicUsize::new(0);
diff --git a/src/test/compile-fail/dupe-symbols-8.rs b/src/test/compile-fail/dupe-symbols-8.rs
new file mode 100644 (file)
index 0000000..3c0e545
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// error-pattern:already defined
+
+
+#![allow(warnings)]
+
+fn main() {
+    {
+        extern fn fail() {}
+    }
+    {
+        extern fn fail() {}
+    }
+}
diff --git a/src/test/compile-fail/empty-comment.rs b/src/test/compile-fail/empty-comment.rs
new file mode 100644 (file)
index 0000000..5c521a5
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// `/**/` was previously regarded as a doc comment because it starts with `/**` and ends with `*/`.
+// This could break some internal logic that assumes the length of a doc comment is at least 5,
+// leading to an ICE.
+
+fn main() {
+    println!(/**/); //~ ERROR unexpected end
+}
diff --git a/src/test/compile-fail/empty-struct-braces-expr.rs b/src/test/compile-fail/empty-struct-braces-expr.rs
new file mode 100644 (file)
index 0000000..6716708
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Can't use empty braced struct as constant or constructor function
+
+#![feature(braced_empty_structs)]
+
+struct Empty1 {}
+
+enum E {
+    Empty2 {}
+}
+
+fn main() {
+    let e1 = Empty1; //~ ERROR `Empty1` is the name of a struct or struct variant
+    let e1 = Empty1(); //~ ERROR `Empty1` is the name of a struct or struct variant
+    let e2 = E::Empty2; //~ ERROR `E::Empty2` is the name of a struct or struct variant
+    let e2 = E::Empty2(); //~ ERROR `E::Empty2` is the name of a struct or struct variant
+}
diff --git a/src/test/compile-fail/empty-struct-braces-gate-1.rs b/src/test/compile-fail/empty-struct-braces-gate-1.rs
new file mode 100644 (file)
index 0000000..a131b46
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Feature gate test for empty struct with braces
+// Can't define an empty braced struct
+
+struct Empty1 {} //~ ERROR empty structs and enum variants with braces are unstable
+struct Empty2;
+
+enum E {
+    Empty4 {}, //~ ERROR empty structs and enum variants with braces are unstable
+    Empty5,
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/empty-struct-braces-gate-2.rs b/src/test/compile-fail/empty-struct-braces-gate-2.rs
new file mode 100644 (file)
index 0000000..c1b73bd
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Feature gate test for empty struct with braces
+// Can't use braced expressions and patterns with structs defined without braces
+
+struct Empty2;
+
+enum E {
+    Empty5,
+}
+
+fn main() {
+    let e2: Empty2 = Empty2 {}; //~ ERROR empty structs and enum variants with braces are unstable
+    let e2: Empty2 = Empty2;
+    // Issue #28692
+    // let e5: E = E::Empty5 {}; // ERROR empty structs and enum variants with braces are unstable
+    let e5: E = E::Empty5;
+
+    match e2 {
+        Empty2 {} => {} //~ ERROR empty structs and enum variants with braces are unstable
+    }
+    match e2 {
+        Empty2 => {}
+    }
+    match e2 {
+        Empty2 { .. } => {} //~ ERROR empty structs and enum variants with braces are unstable
+    }
+    // Issue #28692
+    // match e5 {
+    //     E::Empty5 {} => {} // ERROR empty structs and enum variants with braces are unstable
+    // }
+    match e5 {
+        E::Empty5 => {}
+    }
+    // Issue #28692
+    // match e5 {
+    //     E::Empty5 { .. } => {} // ERROR empty structs and enum variants with braces are unstable
+    // }
+
+    let e22 = Empty2 { ..e2 }; //~ ERROR empty structs and enum variants with braces are unstable
+}
diff --git a/src/test/compile-fail/empty-struct-braces-pat-1.rs b/src/test/compile-fail/empty-struct-braces-pat-1.rs
new file mode 100644 (file)
index 0000000..e095f69
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Can't use empty braced struct as constant pattern
+
+#![deny(warnings)]
+#![feature(braced_empty_structs)]
+
+struct Empty1 {}
+
+enum E {
+    Empty2 {}
+}
+
+fn main() {
+    let e1 = Empty1 {};
+    let e2 = E::Empty2 {};
+
+    // Issue #28692
+    // match e1 {
+    //     Empty1 => () // ERROR incorrect error
+    // }
+    match e2 {
+        E::Empty2 => () //~ ERROR `E::Empty2` does not name a non-struct variant or a tuple struct
+    }
+}
diff --git a/src/test/compile-fail/empty-struct-braces-pat-2.rs b/src/test/compile-fail/empty-struct-braces-pat-2.rs
new file mode 100644 (file)
index 0000000..0e7152e
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Can't use empty braced struct as enum pattern
+
+#![feature(braced_empty_structs)]
+
+struct Empty1 {}
+
+enum E {
+    Empty2 {}
+}
+
+fn main() {
+    let e1 = Empty1 {};
+    let e2 = E::Empty2 {};
+
+    // Rejected by parser as yet
+    // match e1 {
+    //     Empty1() => () // ERROR unresolved enum variant, struct or const `Empty1`
+    // }
+    match e1 {
+        Empty1(..) => () //~ ERROR unresolved enum variant, struct or const `Empty1`
+    }
+    // Issue #28692
+    // match e2 {
+    //     E::Empty2() => () // ERROR unresolved enum variant, struct or const `Empty2`
+    // }
+    // match e2 {
+    //     E::Empty2(..) => () // ERROR unresolved enum variant, struct or const `Empty2`
+    // }
+}
diff --git a/src/test/compile-fail/empty-struct-unit-expr.rs b/src/test/compile-fail/empty-struct-unit-expr.rs
new file mode 100644 (file)
index 0000000..1990656
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Can't use unit struct as constructor function
+
+#![feature(braced_empty_structs)]
+
+struct Empty1;
+
+enum E {
+    Empty2
+}
+
+fn main() {
+    let e1 = Empty1(); //~ ERROR expected function, found `Empty1`
+    let e2 = E::Empty2(); //~ ERROR expected function, found `E`
+}
diff --git a/src/test/compile-fail/empty-struct-unit-pat.rs b/src/test/compile-fail/empty-struct-unit-pat.rs
new file mode 100644 (file)
index 0000000..966a278
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Can't use unit struct as enum pattern
+
+#![feature(braced_empty_structs)]
+
+FIXME //~ ERROR expected item, found `FIXME`
+
+struct Empty1;
+
+enum E {
+    Empty2
+}
+
+fn main() {
+    let e1 = Empty1;
+    let e2 = E::Empty2;
+
+    // Issue #28692
+    // match e1 {
+    //     Empty1() => () // ERROR variable `Empty1` should have a snake case name
+    // }
+    // match e1 {
+    //     Empty1(..) => () // ERROR variable `Empty1` should have a snake case name
+    // }
+    // match e2 {
+    //     E::Empty2() => () // ERROR variable `Empty2` should have a snake case name
+    // }
+    // match e2 {
+    //     E::Empty2(..) => () // ERROR variable `Empty2` should have a snake case name
+    // }
+}
index ace1b399662898d469d7e710c087d35c9543041a..f1bb5c0dea21d64104f100b9878007236bd1fe8a 100644 (file)
@@ -19,8 +19,4 @@
 fn main() {
     let x = box 'c'; //~ ERROR box expression syntax is experimental
     println!("x: {}", x);
-
-    let x = box () 'c'; //~ ERROR box expression syntax is experimental
-    //~^ WARN deprecated syntax
-    println!("x: {}", x);
 }
diff --git a/src/test/compile-fail/feature-gate-cfg-target-vendor.rs b/src/test/compile-fail/feature-gate-cfg-target-vendor.rs
new file mode 100644 (file)
index 0000000..e68a84d
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[cfg(target_vendor = "x")] //~ ERROR `cfg(target_vendor)` is experimental
+#[cfg_attr(target_vendor = "x", x)] //~ ERROR `cfg(target_vendor)` is experimental
+struct Foo(u64, u64);
+
+#[cfg(not(any(all(target_vendor = "x"))))] //~ ERROR `cfg(target_vendor)` is experimental
+fn foo() {}
+
+fn main() {
+    cfg!(target_vendor = "x");
+    //~^ ERROR `cfg(target_vendor)` is experimental and subject to change
+}
diff --git a/src/test/compile-fail/feature-gate-dropck-ugeh.rs b/src/test/compile-fail/feature-gate-dropck-ugeh.rs
new file mode 100644 (file)
index 0000000..aa479a9
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Ensure that attempts to use the unsafe attribute are feature-gated.
+
+// Example adapted from RFC 1238 text (just left out the feature gate).
+
+// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
+//     #example-of-the-unguarded-escape-hatch
+
+// #![feature(dropck_parametricity)]
+
+use std::cell::Cell;
+
+struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>);
+
+struct Foo<T> { data: Vec<T> }
+
+impl<T> Drop for Foo<T> {
+    #[unsafe_destructor_blind_to_params] // This is the UGEH attribute
+    //~^ ERROR unsafe_destructor_blind_to_params has unstable semantics
+    fn drop(&mut self) { }
+}
+
+fn main() {
+    let mut foo = Foo {  data: Vec::new() };
+    foo.data.push(Concrete(0, Cell::new(None)));
+    foo.data.push(Concrete(0, Cell::new(None)));
+
+    foo.data[0].1.set(Some(&foo.data[1]));
+    foo.data[1].1.set(Some(&foo.data[0]));
+}
+
diff --git a/src/test/compile-fail/feature-gate-negate-unsigned.rs b/src/test/compile-fail/feature-gate-negate-unsigned.rs
new file mode 100644 (file)
index 0000000..b1c73fa
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that negating unsigned integers is gated by `negate_unsigned` feature
+// gate
+
+struct S;
+impl std::ops::Neg for S {
+    type Output = u32;
+    fn neg(self) -> u32 { 0 }
+}
+
+const _MAX: usize = -1;
+//~^ ERROR unary negation of unsigned integers may be removed in the future
+
+fn main() {
+    let a = -1;
+    //~^ ERROR unary negation of unsigned integers may be removed in the future
+    let _b : u8 = a; // for infering variable a to u8.
+
+    -a;
+    //~^ ERROR unary negation of unsigned integers may be removed in the future
+
+    let _d = -1u8;
+    //~^ ERROR unary negation of unsigned integers may be removed in the future
+
+    for _ in -10..10u8 {}
+    //~^ ERROR unary negation of unsigned integers may be removed in the future
+
+    -S; // should not trigger the gate; issue 26840
+}
diff --git a/src/test/compile-fail/feature-gate-no-debug.rs b/src/test/compile-fail/feature-gate-no-debug.rs
new file mode 100644 (file)
index 0000000..e185056
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[no_debug] //~ ERROR the `#[no_debug]` attribute is
+fn main() {}
diff --git a/src/test/compile-fail/feature-gate-omit-gdb-pretty-printer-section.rs b/src/test/compile-fail/feature-gate-omit-gdb-pretty-printer-section.rs
new file mode 100644 (file)
index 0000000..a837a7f
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[omit_gdb_pretty_printer_section] //~ ERROR the `#[omit_gdb_pretty_printer_section]` attribute is
+fn main() {}
index 7c75605d57d329e685f689094c182f22bf6fa64f..47a25bf637c5f70167fdc5f04f49f46b90ad6905 100644 (file)
 fn main() {
     use std::boxed::HEAP;
 
-    let x = box (HEAP) 'c'; //~ ERROR placement-in expression syntax is experimental
-    //~^ WARN deprecated syntax
-    println!("x: {}", x);
-
     let x = in HEAP { 'c' }; //~ ERROR placement-in expression syntax is experimental
     println!("x: {}", x);
 }
diff --git a/src/test/compile-fail/feature-gate-pushpop-unsafe.rs b/src/test/compile-fail/feature-gate-pushpop-unsafe.rs
deleted file mode 100644 (file)
index e317b4c..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
-    let c = push_unsafe!('c'); //~ ERROR push/pop_unsafe macros are experimental
-    let c = pop_unsafe!('c'); //~ ERROR push/pop_unsafe macros are experimental
-}
index 54bdaf011c875c63de26a56c6ec368cb0ecfca7d..ae342af4a52afe427af59236a375ba86a67e8e47 100644 (file)
@@ -8,14 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// FIXME #20661: format_args! emits calls to the unstable std::fmt::rt
-// module, so the compiler has some hacks to make that possible
-// (in span_is_internal). Unnfortunately those hacks defeat this
-// particular scenario of checking feature gates in arguments to
-// println!().
-
-// ignore-test
-
 // tests that input to a macro is checked for use of gated features. If this
 // test succeeds due to the acceptance of a feature, pick a new feature to
 // test. Not ideal, but oh well :(
diff --git a/src/test/compile-fail/for-expn-2.rs b/src/test/compile-fail/for-expn-2.rs
deleted file mode 100644 (file)
index ce2315f..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that we get an expansion stack for `for` loops.
-
-// error-pattern:in this expansion of for loop expansion
-
-fn main() {
-    for t in &foo {
-    }
-}
index ff6f848ab598d7313ca216841d7d9a24c73e2c8e..f06882875fd9b4650d29f17b0caf019a30cd7153 100644 (file)
@@ -11,8 +11,6 @@
 // for-loops are expanded in the front end, and use an `iter` ident in their expansion. Check that
 // `iter` is not accessible inside the for loop.
 
-#![allow(unstable)]
-
 fn main() {
     for _ in 0..10 {
         iter.next();  //~ error: unresolved name `iter`
index ab6dc2bab3ecbf98c4b864d4752393f238995e91..81c4db68628d45517bc966725049aefb6ac0e084 100644 (file)
@@ -9,7 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    for
-        &1 //~ ERROR refutable pattern in `for` loop binding
-        in [1].iter() {}
+    for &1 in [1].iter() {} //~ ERROR refutable pattern in `for` loop binding
 }
diff --git a/src/test/compile-fail/invalid-path-in-const.rs b/src/test/compile-fail/invalid-path-in-const.rs
new file mode 100644 (file)
index 0000000..3c4ad5a
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    fn f(a: [u8; u32::DOESNOTEXIST]) {}
+    //~^ ERROR unresolved path in constant expression
+}
index 26ed9d8c26ada9173534443c99b643668d15beb3..6b19cb0b68f10e6c294d9fe30d4c226df3b37b3b 100644 (file)
@@ -12,7 +12,6 @@
 #![feature(placement_in_syntax)]
 
 fn main() {
-    box ( () ) 0;
+    in () { 0 };
     //~^ ERROR: the trait `core::ops::Placer<_>` is not implemented
-    //~| WARN deprecated syntax
 }
index a1663772bad136178b64221f5f38392461eab60a..898e6be6fc85c0ce863a590dcc9a0ec8cc635041 100644 (file)
@@ -16,4 +16,17 @@ fn main() -> (){
     for n in 0..1 {
         println!("{}", f!()); //~ ERROR unresolved name `n`
     }
+
+    if let Some(n) = None {
+        println!("{}", f!()); //~ ERROR unresolved name `n`
+    }
+
+    if false {
+    } else if let Some(n) = None {
+        println!("{}", f!()); //~ ERROR unresolved name `n`
+    }
+
+    while let Some(n) = None {
+        println!("{}", f!()); //~ ERROR unresolved name `n`
+    }
 }
index 653ba165e74397c256bba6d36e690fa98f684926..ec29a84f44e4bd105019295b97c1bb15c69665c6 100644 (file)
 fn main() {
     let values: Vec<u8> = vec![1,2,3,4,5,6,7,8];
 
-    for
-        [x,y,z]
-//~^ ERROR refutable pattern in `for` loop binding: `[]` not covered
-        in values.chunks(3).filter(|&xs| xs.len() == 3) {
+    for [x,y,z] in values.chunks(3).filter(|&xs| xs.len() == 3) {
+        //~^ ERROR refutable pattern in `for` loop binding: `[]` not covered
         println!("y={}", y);
     }
 }
diff --git a/src/test/compile-fail/issue-16819.rs b/src/test/compile-fail/issue-16819.rs
new file mode 100644 (file)
index 0000000..065b29d
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct TS ( //~ ERROR empty tuple structs and enum variants are not allowed
+    #[cfg(untrue)]
+    int,
+);
+
+fn main() {
+    let s = S;
+}
index a481fec6bf96839cb011e0dcc6f50ab1657ecee1..c7d6443663241a27392acbc03f13f6ad8fa700fa 100644 (file)
@@ -11,6 +11,8 @@
 // Test that the parser does not attempt to parse struct literals
 // within assignments in if expressions.
 
+#![allow(unused_parens)]
+
 struct Foo {
     foo: usize
 }
index ff640793afe01f314662a9a26310baad8505fdc4..501f6eb4deaa01b4b662dda31653cd32af7fa1f6 100644 (file)
@@ -15,8 +15,8 @@
 struct Foo;
 
 impl Foo {
-    #[unstable(feature = "test_feature")]
-    #[deprecated(since = "1.0.0")]
+    #[unstable(feature = "test_feature", issue = "0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     fn foo(self) {}
 }
 
index a33ec23a16a51e592bd11bc14fcea980f09b0576..a15ccb71aa733bcf5e64da17fb9012ab2fc45129 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // Test that we can parse a unit struct with a where clause, even if
-// it leads to a error later on since `T` is unused.
+// it leads to an error later on since `T` is unused.
 
 struct Foo<T> where T: Copy; //~ ERROR parameter `T` is never used
 
index 95176da9020d566c9dfdcc8bf3703ad85b1ee5fe..5f6216a898a0b0351da1eedee6977fc948a58234 100644 (file)
@@ -22,6 +22,7 @@ fn foo(b: &Bar) {
     b.foo(&0)
     //~^ ERROR the trait `Foo` is not implemented for the type `Bar`
     //~| ERROR E0038
+    //~| WARNING E0038
 }
 
 fn main() {
index 57eb82a156bbfaf55c6328c74f94cef5ce0d9870..c73a17350648bfba823679cd75eb677bb969c4b1 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Test that when a crate is linked under another name that that name is used in global paths
+//! Test that when a crate is linked under another name that name is used in global paths
 
 extern crate core as bar;
 
diff --git a/src/test/compile-fail/issue-21546.rs b/src/test/compile-fail/issue-21546.rs
new file mode 100644 (file)
index 0000000..bb1bcd4
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Also works as a test for #14564
+
+#[allow(non_snake_case)]
+mod Foo { }
+//~^ NOTE first definition of type or module `Foo`
+
+#[allow(dead_code)]
+struct Foo;
+//~^ WARNING duplicate definition of type or module `Foo`
+
+
+#[allow(non_snake_case)]
+mod Bar { }
+//~^ NOTE first definition of type or module `Bar`
+
+#[allow(dead_code)]
+struct Bar(i32);
+//~^ WARNING duplicate definition of type or module `Bar`
+
+
+#[allow(dead_code)]
+struct Baz(i32);
+//~^ NOTE first definition of type or module
+
+#[allow(non_snake_case)]
+mod Baz { }
+//~^ WARNING duplicate definition of type or module `Baz`
+
+
+#[allow(dead_code)]
+struct Qux { x: bool }
+//~^ NOTE first definition of type or module
+
+#[allow(non_snake_case)]
+mod Qux { }
+//~^ WARNING duplicate definition of type or module `Qux`
+
+
+#[allow(dead_code)]
+struct Quux;
+//~^ NOTE first definition of type or module
+
+#[allow(non_snake_case)]
+mod Quux { }
+//~^ WARNING duplicate definition of type or module `Quux`
+
+
+#[allow(dead_code)]
+enum Corge { A, B }
+
+#[allow(non_snake_case)]
+mod Corge { }
+//~^ ERROR duplicate definition of type or module `Corge`
+
+fn main() { }
diff --git a/src/test/compile-fail/issue-22599.rs b/src/test/compile-fail/issue-22599.rs
new file mode 100644 (file)
index 0000000..b9ea358
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(unused_variables)]
+
+fn f(_: i32) {}
+
+fn main() {
+    let mut v = 0;
+    f(v);
+    v = match 0 { a => 0 }; //~ ERROR: unused variable: `a`
+    f(v);
+}
diff --git a/src/test/compile-fail/issue-22872.rs b/src/test/compile-fail/issue-22872.rs
deleted file mode 100644 (file)
index 8698228..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-trait Wrap<'b> {
-    fn foo(&'b mut self);
-}
-
-struct Wrapper<P>(P);
-
-impl<'b, P> Wrap<'b> for Wrapper<P>
-where P: Process<'b>,
-      <P as Process<'b>>::Item: Iterator {
-    fn foo(&mut self) {}
-}
-
-
-pub trait Process<'a> {
-    type Item;
-    fn bar(&'a self);
-}
-
-fn push_process<P>(process: P) where P: Process<'static> {
-    let _: Box<for<'b> Wrap<'b>> = Box::new(Wrapper(process));
-    //~^ ERROR the trait `for<'b> Process<'b>` is not implemented for the type `P` [E0277]
-    //~| ERROR the trait `for<'b> core::iter::Iterator` is not implemented for the type
-    //~| ERROR cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting
-}
-
-fn main() {}
index 8c83c4cefd1913701647cbdfd2108088ac2cfcbe..dba9c32f9b4808e4a2d82ccd05404ce56c82c323 100644 (file)
@@ -24,7 +24,7 @@ pub fn let_<'var, VAR, F: for<'v: 'var> Fn(Expr<'v, VAR>) -> Expr<'v, VAR>>
 }
 
 fn main() {
-    let ex =  (|x| {
+    let ex = |x| {
         let_(add(x,x), |y| { //~ ERROR unable to infer enough type information about `_`
-            let_(add(x, x), |x|x)})});
+            let_(add(x, x), |x|x)})};
 }
diff --git a/src/test/compile-fail/issue-23543.rs b/src/test/compile-fail/issue-23543.rs
new file mode 100644 (file)
index 0000000..4ed4415
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub trait A: Copy {}
+
+struct Foo;
+
+pub trait D {
+    fn f<T>(self)
+        where T<Bogus = Foo>: A;
+        //~^ ERROR associated type bindings are not allowed here [E0229]
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-23544.rs b/src/test/compile-fail/issue-23544.rs
new file mode 100644 (file)
index 0000000..1d7c218
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub trait A: Copy {}
+
+pub trait D {
+    fn f<T>(self)
+        where T<Bogus = Self::AlsoBogus>: A;
+        //~^ ERROR associated type bindings are not allowed here [E0229]
+}
+
+fn main() {}
index 3d77d171acebf871915c4c2548b80b9979f505ac..f98cf6575d6ec5b2340b65bd2b8cd27462762b81 100644 (file)
@@ -26,7 +26,7 @@ fn main() {
                     self.pos += 1;
                     Some(next_val)
                 } else {
-                    let next_val = (self.mem[0] + self.mem[1]);
+                    let next_val = self.mem[0] + self.mem[1];
                     self.mem[0] = self.mem[1];
                     self.mem[1] = next_val;
                     Some(next_val)
diff --git a/src/test/compile-fail/issue-25145.rs b/src/test/compile-fail/issue-25145.rs
new file mode 100644 (file)
index 0000000..e8a9c8d
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(associated_consts)]
+
+struct S;
+
+impl S {
+    const N: usize = 3;
+}
+
+static STUFF: [u8; S::N] = [0; S::N];
+//~^ ERROR array length constant evaluation error: unresolved path in constant expression
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-26056.rs b/src/test/compile-fail/issue-26056.rs
new file mode 100644 (file)
index 0000000..4e9cbc4
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait MapLookup<Q> {
+    type MapValue;
+}
+
+impl<K> MapLookup<K> for K {
+    type MapValue = K;
+}
+
+trait Map: MapLookup<<Self as Map>::Key> {
+    type Key;
+}
+
+impl<K> Map for K {
+    type Key = K;
+}
+
+
+fn main() {
+    let _ = &()
+        as &Map<Key=u32,MapValue=u32>;
+    //~^ ERROR the trait `Map` cannot be made into an object
+    //~| NOTE the trait cannot use `Self` as a type parameter
+}
diff --git a/src/test/compile-fail/issue-26459.rs b/src/test/compile-fail/issue-26459.rs
new file mode 100644 (file)
index 0000000..48eda91
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    match 'a' {
+        char{ch} => true
+        //~^ ERROR `char` does not name a struct or a struct variant
+    };
+}
diff --git a/src/test/compile-fail/issue-26886.rs b/src/test/compile-fail/issue-26886.rs
new file mode 100644 (file)
index 0000000..c849716
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::sync::{self, Arc}; //~ NOTE previous import
+                            //~^ NOTE previous import
+use std::sync::Arc; //~ ERROR a type named
+use std::sync; //~ ERROR a module named
+
+fn main() {
+}
diff --git a/src/test/compile-fail/issue-26905.rs b/src/test/compile-fail/issue-26905.rs
new file mode 100644 (file)
index 0000000..3b8fac8
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(unsize, coerce_unsized)]
+
+// Verfies that non-PhantomData ZSTs still cause coercions to fail.
+// They might have additional semantics that we don't want to bulldoze.
+
+use std::marker::{Unsize, PhantomData};
+use std::ops::CoerceUnsized;
+
+struct NotPhantomData<T: ?Sized>(PhantomData<T>);
+
+struct MyRc<T: ?Sized> {
+    _ptr: *const T,
+    _boo: NotPhantomData<T>,
+}
+
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<MyRc<U>> for MyRc<T>{ } //~ERROR
+
+fn main() {
+    let data = [1, 2, 3];
+    let iter = data.iter();
+    let x = MyRc { _ptr: &iter, _boo: NotPhantomData(PhantomData) };
+    let _y: MyRc<Iterator<Item=&u32>> = x;
+}
+
index 336368cf8a49d73e948893533dcfea9091bafc6e..3cdb370f0e94c9156e62c52061ab7bb6a5c00601 100644 (file)
@@ -22,8 +22,8 @@ fn main() {
     let Foo { .. } = x; //~ ERROR `Foo` does not name a struct
 
     let x = Bar;
-    Bar { ..x }; //~ ERROR `Bar` does not name a structure
-    let Bar { .. } = x; //~ ERROR `Bar` does not name a struct
+    Bar { ..x }; //~ ERROR empty structs and enum variants with braces are unstable
+    let Bar { .. } = x; //~ ERROR empty structs and enum variants with braces are unstable
 
     match Enum::Bar {
         Enum::Bar { .. } //~ ERROR `Enum::Bar` does not name a struct
diff --git a/src/test/compile-fail/issue-27895.rs b/src/test/compile-fail/issue-27895.rs
new file mode 100644 (file)
index 0000000..959818b
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let i = 5;
+    let index = 6;
+
+    match i {
+        0...index => println!("winner"),
+        //~^ ERROR paths in constants may only refer to constants or functions
+        //~| ERROR non-constant path in constant expression
+        _ => println!("hello"),
+    }
+}
diff --git a/src/test/compile-fail/issue-28075.rs b/src/test/compile-fail/issue-28075.rs
new file mode 100644 (file)
index 0000000..d75f5f6
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Unstable entities should be caught in import lists
+
+// aux-build:lint_stability.rs
+
+#![allow(unused_imports)]
+
+extern crate lint_stability;
+
+use lint_stability::{unstable, deprecated}; //~ ERROR use of unstable library feature 'test_feature'
+//~^ WARNING use of deprecated item
+
+use lint_stability::unstable::{self as u}; //~ ERROR use of unstable library feature 'test_feature'
+
+fn main() {
+}
diff --git a/src/test/compile-fail/issue-28388-1.rs b/src/test/compile-fail/issue-28388-1.rs
new file mode 100644 (file)
index 0000000..ef97b40
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc.
+
+use foo::{}; //~ ERROR failed to resolve. foo
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-28388-2.rs b/src/test/compile-fail/issue-28388-2.rs
new file mode 100644 (file)
index 0000000..837dc67
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc.
+
+mod m {
+    mod n {}
+}
+
+use m::n::{}; //~ ERROR module `n` is private
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-28388-3.rs b/src/test/compile-fail/issue-28388-3.rs
new file mode 100644 (file)
index 0000000..0cb669f
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc.
+
+// aux-build:lint_stability.rs
+
+extern crate lint_stability;
+
+use lint_stability::UnstableStruct::{}; //~ ERROR use of unstable library feature 'test_feature'
+use lint_stability::StableStruct::{}; // OK
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-28433.rs b/src/test/compile-fail/issue-28433.rs
new file mode 100644 (file)
index 0000000..3ca2213
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum bird {
+    pub duck,
+    //~^ ERROR: expected identifier, found keyword `pub`
+    //~^^ ERROR: expected
+    goose
+}
+
+
+fn main() {
+    let y = bird::goose;
+}
diff --git a/src/test/compile-fail/issue-28472.rs b/src/test/compile-fail/issue-28472.rs
new file mode 100644 (file)
index 0000000..23827c5
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that the visibility modifier is included in the span of foreign items.
+
+extern {
+  fn foo();
+
+  pub //~ ERROR duplicate definition
+  fn foo();
+
+  pub //~ ERROR duplicate definition
+  static mut foo: u32;
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/issue-28576.rs b/src/test/compile-fail/issue-28576.rs
new file mode 100644 (file)
index 0000000..bd71867
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub trait Foo<RHS=Self> {
+    type Assoc;
+}
+
+pub trait Bar: Foo<Assoc=()> {
+    fn new(&self, b: &
+           Bar //~ ERROR the trait `Bar` cannot be made into an object
+              <Assoc=()>
+    );
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-28776.rs b/src/test/compile-fail/issue-28776.rs
new file mode 100644 (file)
index 0000000..ce06c8b
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::ptr;
+
+fn main() {
+    (&ptr::write)(1 as *mut _, 42); //~ ERROR E0133
+}
diff --git a/src/test/compile-fail/issue-28837.rs b/src/test/compile-fail/issue-28837.rs
new file mode 100644 (file)
index 0000000..c7cf63b
--- /dev/null
@@ -0,0 +1,60 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct A;
+
+fn main() {
+    let a = A;
+
+    a + a; //~ ERROR binary operation `+` cannot be applied to type `A`
+    //~^ NOTE an implementation of `std::ops::Add` might be missing for `A`
+
+    a - a; //~ ERROR binary operation `-` cannot be applied to type `A`
+    //~^ NOTE an implementation of `std::ops::Sub` might be missing for `A`
+
+    a * a; //~ ERROR binary operation `*` cannot be applied to type `A`
+    //~^ NOTE an implementation of `std::ops::Mul` might be missing for `A`
+
+    a / a; //~ ERROR binary operation `/` cannot be applied to type `A`
+    //~^ NOTE an implementation of `std::ops::Div` might be missing for `A`
+
+    a % a; //~ ERROR binary operation `%` cannot be applied to type `A`
+    //~^ NOTE an implementation of `std::ops::Rem` might be missing for `A`
+
+    a & a; //~ ERROR binary operation `&` cannot be applied to type `A`
+    //~^ NOTE an implementation of `std::ops::BitAnd` might be missing for `A`
+
+    a | a; //~ ERROR binary operation `|` cannot be applied to type `A`
+    //~^ NOTE an implementation of `std::ops::BitOr` might be missing for `A`
+
+    a << a; //~ ERROR binary operation `<<` cannot be applied to type `A`
+    //~^ NOTE an implementation of `std::ops::Shl` might be missing for `A`
+
+    a >> a; //~ ERROR binary operation `>>` cannot be applied to type `A`
+    //~^ NOTE an implementation of `std::ops::Shr` might be missing for `A`
+
+    a == a; //~ ERROR binary operation `==` cannot be applied to type `A`
+    //~^ NOTE an implementation of `std::cmp::PartialEq` might be missing for `A`
+
+    a != a; //~ ERROR binary operation `!=` cannot be applied to type `A`
+    //~^ NOTE an implementation of `std::cmp::PartialEq` might be missing for `A`
+
+    a < a; //~ ERROR binary operation `<` cannot be applied to type `A`
+    //~^ NOTE an implementation of `std::cmp::PartialOrd` might be missing for `A`
+
+    a <= a; //~ ERROR binary operation `<=` cannot be applied to type `A`
+    //~^ NOTE an implementation of `std::cmp::PartialOrd` might be missing for `A`
+
+    a > a; //~ ERROR binary operation `>` cannot be applied to type `A`
+    //~^ NOTE an implementation of `std::cmp::PartialOrd` might be missing for `A`
+
+    a >= a; //~ ERROR binary operation `>=` cannot be applied to type `A`
+    //~^ NOTE an implementation of `std::cmp::PartialOrd` might be missing for `A`
+}
diff --git a/src/test/compile-fail/issue-29106.rs b/src/test/compile-fail/issue-29106.rs
new file mode 100644 (file)
index 0000000..1872c62
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::rc::Rc;
+use std::sync::Arc;
+
+struct Foo<'a>(&'a String);
+
+impl<'a> Drop for Foo<'a> {
+    fn drop(&mut self) {
+        println!("{:?}", self.0);
+    }
+}
+
+fn main() {
+    {
+        let (y, x);
+        x = "alive".to_string();
+        y = Arc::new(Foo(&x)); //~ ERROR `x` does not live long enough
+    }
+
+    {
+        let (y, x);
+        x = "alive".to_string();
+        y = Rc::new(Foo(&x)); //~ ERROR `x` does not live long enough
+    }
+}
diff --git a/src/test/compile-fail/issue-29161.rs b/src/test/compile-fail/issue-29161.rs
new file mode 100644 (file)
index 0000000..1821f57
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod a {
+    struct A;
+
+    impl Default for A {
+        pub fn default() -> A {
+            //~^ ERROR E0449
+            A;
+        }
+    }
+}
+
+
+fn main() {
+    a::A::default();
+    //~^ ERROR method `default` is inaccessible
+ }
diff --git a/src/test/compile-fail/issue-29181.rs b/src/test/compile-fail/issue-29181.rs
new file mode 100644 (file)
index 0000000..2fcec51
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:issue-29181.rs
+
+extern crate issue_29181 as foo;
+
+fn main() {
+    0.homura(); //~ ERROR no method named `homura` found
+}
diff --git a/src/test/compile-fail/issue-29184.rs b/src/test/compile-fail/issue-29184.rs
new file mode 100644 (file)
index 0000000..98fe12c
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let x: typeof(92) = 92; //~ ERROR `typeof` is a reserved keyword
+}
diff --git a/src/test/compile-fail/issue-3993-2.rs b/src/test/compile-fail/issue-3993-2.rs
deleted file mode 100644 (file)
index 9d9e91a..0000000
+++ /dev/null
@@ -1,23 +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.
-
-use zoo::bird::{duck, goose};
-
-mod zoo {
-    pub enum bird {
-        pub duck, //~ ERROR: unnecessary `pub` visibility
-        goose
-    }
-}
-
-
-fn main() {
-    let y = goose;
-}
index 8261862c5fc518545718f7605f423e4e113a4670..792d27c179bc4fb70ddf4d65278689f8ccb2913e 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Creating a stack closure which references an box and then
+// Creating a stack closure which references a box and then
 // transferring ownership of the box before invoking the stack
 // closure results in a crash.
 
index 9c2e8d278ab0b8310db1190bd21c2ee27c824730..95921556c7db1de120f85c73887fc83e8fe23c87 100644 (file)
@@ -8,48 +8,50 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![deny(const_err)]
+
 use std::{isize, i8, i16, i32, i64};
 use std::thread;
 
 fn main() {
     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
-    //~^ ERROR attempted to divide with overflow in a constant expression
+    //~^ ERROR attempted to divide with overflow
     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
-    //~^ ERROR attempted to divide with overflow in a constant expression
+    //~^ ERROR attempted to divide with overflow
     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
-    //~^ ERROR attempted to divide with overflow in a constant expression
+    //~^ ERROR attempted to divide with overflow
     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
-    //~^ ERROR attempted to divide with overflow in a constant expression
+    //~^ ERROR attempted to divide with overflow
     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
-    //~^ ERROR attempted to divide with overflow in a constant expression
+    //~^ ERROR attempted to divide with overflow
     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
-    //~^ ERROR attempted to divide by zero in a constant expression
+    //~^ ERROR attempted to divide by zero
     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
-    //~^ ERROR attempted to divide by zero in a constant expression
+    //~^ ERROR attempted to divide by zero
     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
-    //~^ ERROR attempted to divide by zero in a constant expression
+    //~^ ERROR attempted to divide by zero
     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
-    //~^ ERROR attempted to divide by zero in a constant expression
+    //~^ ERROR attempted to divide by zero
     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
-    //~^ ERROR attempted to divide by zero in a constant expression
+    //~^ ERROR attempted to divide by zero
     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
-    //~^ ERROR attempted remainder with overflow in a constant expression
+    //~^ ERROR attempted remainder with overflow
     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
-    //~^ ERROR attempted remainder with overflow in a constant expression
+    //~^ ERROR attempted remainder with overflow
     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
-    //~^ ERROR attempted remainder with overflow in a constant expression
+    //~^ ERROR attempted remainder with overflow
     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
-    //~^ ERROR attempted remainder with overflow in a constant expression
+    //~^ ERROR attempted remainder with overflow
     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
-    //~^ ERROR attempted remainder with overflow in a constant expression
+    //~^ ERROR attempted remainder with overflow
     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
-    //~^ ERROR attempted remainder with a divisor of zero in a constant expression
+    //~^ ERROR attempted remainder with a divisor of zero
     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
-    //~^ ERROR attempted remainder with a divisor of zero in a constant expression
+    //~^ ERROR attempted remainder with a divisor of zero
     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
-    //~^ ERROR attempted remainder with a divisor of zero in a constant expression
+    //~^ ERROR attempted remainder with a divisor of zero
     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
-    //~^ ERROR attempted remainder with a divisor of zero in a constant expression
+    //~^ ERROR attempted remainder with a divisor of zero
     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
-    //~^ ERROR attempted remainder with a divisor of zero in a constant expression
+    //~^ ERROR attempted remainder with a divisor of zero
 }
diff --git a/src/test/compile-fail/issue28498-reject-ex1.rs b/src/test/compile-fail/issue28498-reject-ex1.rs
new file mode 100644 (file)
index 0000000..cee7c57
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Example taken from RFC 1238 text
+
+// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
+//     #examples-of-code-that-will-start-to-be-rejected
+
+// Compare against test/run-pass/issue28498-must-work-ex2.rs
+
+use std::cell::Cell;
+
+struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>);
+
+struct Foo<T> { data: Vec<T> }
+
+fn potentially_specialized_wrt_t<T>(t: &T) {
+    // Hypothetical code that does one thing for generic T and then is
+    // specialized for T == Concrete (and the specialized form can
+    // then access a reference held in concrete tuple).
+    //
+    // (We don't have specialization yet, but we want to allow for it
+    // in the future.)
+}
+
+impl<T> Drop for Foo<T> {
+    fn drop(&mut self) {
+        potentially_specialized_wrt_t(&self.data[0])
+    }
+}
+
+fn main() {
+    let mut foo = Foo {  data: Vec::new() };
+    foo.data.push(Concrete(0, Cell::new(None)));
+    foo.data.push(Concrete(0, Cell::new(None)));
+
+    foo.data[0].1.set(Some(&foo.data[1]));
+    //~^ ERROR `foo.data` does not live long enough
+    foo.data[1].1.set(Some(&foo.data[0]));
+    //~^ ERROR `foo.data` does not live long enough
+}
diff --git a/src/test/compile-fail/issue28498-reject-lifetime-param.rs b/src/test/compile-fail/issue28498-reject-lifetime-param.rs
new file mode 100644 (file)
index 0000000..92028c7
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Demonstrate that having a lifetime param causes dropck to reject code
+// that might indirectly access previously dropped value.
+//
+// Compare with run-pass/issue28498-ugeh-with-lifetime-param.rs
+
+#[derive(Debug)]
+struct ScribbleOnDrop(String);
+
+impl Drop for ScribbleOnDrop {
+    fn drop(&mut self) {
+        self.0 = format!("DROPPED");
+    }
+}
+
+struct Foo<'a>(u32, &'a ScribbleOnDrop);
+
+impl<'a> Drop for Foo<'a> {
+    fn drop(&mut self) {
+        // Use of `unsafe_destructor_blind_to_params` is unsound,
+        // because destructor accesses borrowed data in `self.1`
+        // and we must force that to strictly outlive `self`.
+        println!("Dropping Foo({}, {:?})", self.0, self.1);
+    }
+}
+
+fn main() {
+    let (last_dropped, foo0);
+    let (foo1, first_dropped);
+
+    last_dropped = ScribbleOnDrop(format!("last"));
+    first_dropped = ScribbleOnDrop(format!("first"));
+    foo0 = Foo(0, &last_dropped);
+    //~^ ERROR `last_dropped` does not live long enough
+    foo1 = Foo(1, &first_dropped);
+    //~^ ERROR `first_dropped` does not live long enough
+
+    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
+}
diff --git a/src/test/compile-fail/issue28498-reject-passed-to-fn.rs b/src/test/compile-fail/issue28498-reject-passed-to-fn.rs
new file mode 100644 (file)
index 0000000..27378b1
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Demonstrate that a type param in negative position causes dropck to reject code
+// that might indirectly access previously dropped value.
+//
+// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs
+
+#[derive(Debug)]
+struct ScribbleOnDrop(String);
+
+impl Drop for ScribbleOnDrop {
+    fn drop(&mut self) {
+        self.0 = format!("DROPPED");
+    }
+}
+
+struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>);
+
+impl<T> Drop for Foo<T> {
+    fn drop(&mut self) {
+        // Use of `unsafe_destructor_blind_to_params` is unsound,
+        // because we pass `T` to the callback in `self.2`
+        // below, and thus potentially read from borrowed data.
+        println!("Dropping Foo({}, {})", self.0, (self.2)(&self.1));
+    }
+}
+
+fn callback(s: & &ScribbleOnDrop) -> String { format!("{:?}", s) }
+
+fn main() {
+    let (last_dropped, foo0);
+    let (foo1, first_dropped);
+
+    last_dropped = ScribbleOnDrop(format!("last"));
+    first_dropped = ScribbleOnDrop(format!("first"));
+    foo0 = Foo(0, &last_dropped, Box::new(callback));
+    //~^ ERROR `last_dropped` does not live long enough
+    foo1 = Foo(1, &first_dropped, Box::new(callback));
+    //~^ ERROR `first_dropped` does not live long enough
+
+    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
+}
diff --git a/src/test/compile-fail/issue28498-reject-trait-bound.rs b/src/test/compile-fail/issue28498-reject-trait-bound.rs
new file mode 100644 (file)
index 0000000..3904d68
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Demonstrate that having a trait bound causes dropck to reject code
+// that might indirectly access previously dropped value.
+//
+// Compare with run-pass/issue28498-ugeh-with-trait-bound.rs
+
+use std::fmt;
+
+#[derive(Debug)]
+struct ScribbleOnDrop(String);
+
+impl Drop for ScribbleOnDrop {
+    fn drop(&mut self) {
+        self.0 = format!("DROPPED");
+    }
+}
+
+struct Foo<T:fmt::Debug>(u32, T);
+
+impl<T:fmt::Debug> Drop for Foo<T> {
+    fn drop(&mut self) {
+        // Use of `unsafe_destructor_blind_to_params` is unsound,
+        // because we access `T` fmt method when we pass `self.1`
+        // below, and thus potentially read from borrowed data.
+        println!("Dropping Foo({}, {:?})", self.0, self.1);
+    }
+}
+
+fn main() {
+    let (last_dropped, foo0);
+    let (foo1, first_dropped);
+
+    last_dropped = ScribbleOnDrop(format!("last"));
+    first_dropped = ScribbleOnDrop(format!("first"));
+    foo0 = Foo(0, &last_dropped);
+    //~^ ERROR `last_dropped` does not live long enough
+    foo1 = Foo(1, &first_dropped);
+    //~^ ERROR `first_dropped` does not live long enough
+
+    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
+}
index d95ed7f10bd17dfc63cb15e897c1f4bf85dc0339..c22ad3182ddaa15467b72b6dd03c645879923e13 100644 (file)
@@ -14,7 +14,8 @@
 #![feature(foo)] //~ ERROR unused or unknown feature
 
 extern crate lint_output_format; //~ ERROR use of unstable library feature
-use lint_output_format::{foo, bar};
+use lint_output_format::{foo, bar}; //~ ERROR use of unstable library feature
+//~^ WARNING use of deprecated item: text,
 
 fn main() {
     let _x = foo(); //~ WARNING #[warn(deprecated)] on by default
index 7e675ca0bc40d5587f19461c5cbf34273418a90f..11f641196807e73600fe97d69fb76b353ce5a805 100644 (file)
@@ -189,7 +189,7 @@ mod this_crate {
         inherit: u8,
         #[unstable(feature = "test_feature", issue = "0")]
         override1: u8,
-        #[deprecated(since = "1.0.0")]
+        #[deprecated(since = "1.0.0", reason = "text")]
         #[unstable(feature = "test_feature", issue = "0")]
         override2: u8,
     }
@@ -198,14 +198,14 @@ mod this_crate {
     struct Stable2(u8,
                    #[stable(feature = "rust1", since = "1.0.0")] u8,
                    #[unstable(feature = "test_feature", issue = "0")]
-                   #[deprecated(since = "1.0.0")] u8);
+                   #[deprecated(since = "1.0.0", reason = "text")] u8);
 
     #[unstable(feature = "test_feature", issue = "0")]
     struct Unstable {
         inherit: u8,
         #[stable(feature = "rust1", since = "1.0.0")]
         override1: u8,
-        #[deprecated(since = "1.0.0")]
+        #[deprecated(since = "1.0.0", reason = "text")]
         #[unstable(feature = "test_feature", issue = "0")]
         override2: u8,
     }
@@ -214,10 +214,10 @@ mod this_crate {
     struct Unstable2(u8,
                      #[stable(feature = "rust1", since = "1.0.0")] u8,
                      #[unstable(feature = "test_feature", issue = "0")]
-                     #[deprecated(since = "1.0.0")] u8);
+                     #[deprecated(since = "1.0.0", reason = "text")] u8);
 
     #[unstable(feature = "test_feature", issue = "0")]
-    #[deprecated(feature = "rust1", since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     struct Deprecated {
         inherit: u8,
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -227,7 +227,7 @@ mod this_crate {
     }
 
     #[unstable(feature = "test_feature", issue = "0")]
-    #[deprecated(feature = "rust1", since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     struct Deprecated2(u8,
                        #[stable(feature = "rust1", since = "1.0.0")] u8,
                        #[unstable(feature = "test_feature", issue = "0")] u8);
index 6cc73ded9750f77e473d297a9e64beb69b01dd57..864aafe5a6b6ffff707e20f4b1963275ca6bdaf0 100644 (file)
@@ -258,7 +258,7 @@ mod inheritance {
 
 mod this_crate {
     #[unstable(feature = "test_feature", issue = "0")]
-    #[deprecated(since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     pub fn deprecated() {}
     #[unstable(feature = "test_feature", issue = "0")]
     #[deprecated(since = "1.0.0", reason = "text")]
@@ -271,7 +271,7 @@ mod this_crate {
 
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn stable() {}
-    #[stable(feature = "rust1", since = "1.0.0", reason = "text")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn stable_text() {}
 
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -279,7 +279,7 @@ mod this_crate {
 
     impl MethodTester {
         #[unstable(feature = "test_feature", issue = "0")]
-        #[deprecated(since = "1.0.0")]
+        #[deprecated(since = "1.0.0", reason = "text")]
         pub fn method_deprecated(&self) {}
         #[unstable(feature = "test_feature", issue = "0")]
         #[deprecated(since = "1.0.0", reason = "text")]
@@ -292,13 +292,13 @@ mod this_crate {
 
         #[stable(feature = "rust1", since = "1.0.0")]
         pub fn method_stable(&self) {}
-        #[stable(feature = "rust1", since = "1.0.0", reason = "text")]
+        #[stable(feature = "rust1", since = "1.0.0")]
         pub fn method_stable_text(&self) {}
     }
 
     pub trait Trait {
         #[unstable(feature = "test_feature", issue = "0")]
-        #[deprecated(since = "1.0.0")]
+        #[deprecated(since = "1.0.0", reason = "text")]
         fn trait_deprecated(&self) {}
         #[unstable(feature = "test_feature", issue = "0")]
         #[deprecated(since = "1.0.0", reason = "text")]
@@ -311,14 +311,14 @@ mod this_crate {
 
         #[stable(feature = "rust1", since = "1.0.0")]
         fn trait_stable(&self) {}
-        #[stable(feature = "rust1", since = "1.0.0", reason = "text")]
+        #[stable(feature = "rust1", since = "1.0.0")]
         fn trait_stable_text(&self) {}
     }
 
     impl Trait for MethodTester {}
 
     #[unstable(feature = "test_feature", issue = "0")]
-    #[deprecated(since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     pub struct DeprecatedStruct {
         #[stable(feature = "test_feature", since = "1.0.0")] i: isize
     }
@@ -332,7 +332,7 @@ mod this_crate {
     }
 
     #[unstable(feature = "test_feature", issue = "0")]
-    #[deprecated(since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     pub struct DeprecatedUnitStruct;
     #[unstable(feature = "test_feature", issue = "0")]
     pub struct UnstableUnitStruct;
@@ -341,7 +341,7 @@ mod this_crate {
 
     pub enum Enum {
         #[unstable(feature = "test_feature", issue = "0")]
-        #[deprecated(since = "1.0.0")]
+        #[deprecated(since = "1.0.0", reason = "text")]
         DeprecatedVariant,
         #[unstable(feature = "test_feature", issue = "0")]
         UnstableVariant,
@@ -351,7 +351,7 @@ mod this_crate {
     }
 
     #[unstable(feature = "test_feature", issue = "0")]
-    #[deprecated(since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     pub struct DeprecatedTupleStruct(isize);
     #[unstable(feature = "test_feature", issue = "0")]
     pub struct UnstableTupleStruct(isize);
@@ -472,7 +472,7 @@ mod this_crate {
     }
 
     #[unstable(feature = "test_feature", issue = "0")]
-    #[deprecated(since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     fn test_fn_body() {
         fn fn_in_body() {}
         fn_in_body();
@@ -480,7 +480,7 @@ mod this_crate {
 
     impl MethodTester {
         #[unstable(feature = "test_feature", issue = "0")]
-        #[deprecated(since = "1.0.0")]
+        #[deprecated(since = "1.0.0", reason = "text")]
         fn test_method_body(&self) {
             fn fn_in_body() {}
             fn_in_body();
@@ -488,7 +488,7 @@ mod this_crate {
     }
 
     #[unstable(feature = "test_feature", issue = "0")]
-    #[deprecated(since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "text")]
     pub trait DeprecatedTrait {
         fn dummy(&self) { }
     }
index c6dc3b70bef37d881f3e12196ecb84b493cc0045..d34738282eb268e0d90f430307433a333dfa13f4 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(visible_private_types)]
 #![allow(dead_code)]
 #![crate_type="lib"]
 
index 12de4a714efc5dc6b6f6cd526b346f5aa5cef21e..cd320ba148aba8fe02323db6fa3fcbae88ac67f3 100644 (file)
@@ -18,5 +18,5 @@ fn forever() -> ! {
 }
 
 fn main() {
-  if (1 == 2) { forever(); }
+  if 1 == 2 { forever(); }
 }
index e1d462d1700029432450a5f37b03d5a986d9fbff..a4d3e3ee02f570bd29c076ceaa93db8485364f0a 100644 (file)
@@ -11,8 +11,7 @@
 #![feature(box_syntax)]
 
 fn dup(x: Box<isize>) -> Box<(Box<isize>,Box<isize>)> {
-    box() (x, x) //~ ERROR use of moved value
-    //~^ WARN deprecated syntax
+    box (x, x) //~ ERROR use of moved value
 }
 fn main() {
     dup(box 3);
index de419a259a24cf4fc0efb6d21eb37bdc2af8c746..06d2441d3c0245b1b9a2aa6bdc4a1dc769f037aa 100644 (file)
@@ -20,12 +20,13 @@ trait Expr: Debug + PartialEq {
 #[derive(Debug)]
 struct SExpr<'x> {
     elements: Vec<Box<Expr+ 'x>>,
+    //~^ ERROR E0038
 }
 
 impl<'x> PartialEq for SExpr<'x> {
     fn eq(&self, other:&SExpr<'x>) -> bool {
         println!("L1: {} L2: {}", self.elements.len(), other.elements.len());
-        //~^ ERROR E0038
+
         let result = self.elements.len() == other.elements.len();
 
         println!("Got compare {}", result);
@@ -44,8 +45,8 @@ impl <'x> Expr for SExpr<'x> {
 }
 
 fn main() {
-    let a: Box<Expr> = Box::new(SExpr::new()); //~ ERROR E0038
-    let b: Box<Expr> = Box::new(SExpr::new()); //~ ERROR E0038
+    let a: Box<Expr> = Box::new(SExpr::new());
+    let b: Box<Expr> = Box::new(SExpr::new());
 
     // assert_eq!(a , b);
 }
index ba82635a4016e16a0b57c59ac7bec7e33017ab5d..0a79ec30e4b942445b96da9bc08f970a4b023f01 100644 (file)
@@ -23,9 +23,9 @@ fn make_bar<T:Bar<u32>>(t: &T) -> &Bar<u32> {
 }
 
 fn make_baz<T:Baz>(t: &T) -> &Baz {
+    //~^ ERROR E0038
+    //~| NOTE the trait cannot use `Self` as a type parameter in the supertrait listing
     t
-        //~^ ERROR E0038
-        //~| NOTE the trait cannot use `Self` as a type parameter in the supertrait listing
 }
 
 fn main() {
index 82425d2c22708760bc5d67ecc4683615de8b1836..2c345e6c8ab2bcd52aace101c8292d51f171557a 100644 (file)
@@ -13,7 +13,7 @@
 // the error points to the start of the file, not the line with the
 // transmute
 
-// error-pattern: transmute called on types with different size
+// error-pattern: transmute called with differently sized types
 
 use std::mem;
 
index 1b164709ac73c4f7303144ae7c239840a06d62d1..94f2522f3eb340e4a8fd809def65bcfb44695ada 100644 (file)
@@ -13,7 +13,7 @@
 // the error points to the start of the file, not the line with the
 // transmute
 
-// error-pattern: transmute called on types with different size
+// error-pattern: transmute called with differently sized types
 
 use std::mem;
 
diff --git a/src/test/compile-fail/placement-expr-unsafe.rs b/src/test/compile-fail/placement-expr-unsafe.rs
new file mode 100644 (file)
index 0000000..50a840e
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that placement in respects unsafe code checks.
+
+#![feature(box_heap)]
+#![feature(placement_in_syntax)]
+
+fn main() {
+    use std::boxed::HEAP;
+
+    let p: *const i32 = &42;
+    let _ = in HEAP { *p }; //~ ERROR requires unsafe
+
+    let p: *const _ = &HEAP;
+    let _ = in *p { 42 }; //~ ERROR requires unsafe
+}
diff --git a/src/test/compile-fail/placement-expr-unstable.rs b/src/test/compile-fail/placement-expr-unstable.rs
new file mode 100644 (file)
index 0000000..d981b71
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that placement in respects unstable code checks.
+
+#![feature(placement_in_syntax)]
+#![feature(core)]
+
+extern crate core;
+
+fn main() {
+    use std::boxed::HEAP; //~ ERROR use of unstable library feature
+
+    let _ = in HEAP { //~ ERROR use of unstable library feature
+        ::core::raw::Slice { //~ ERROR use of unstable library feature
+            data: &42, //~ ERROR use of unstable library feature
+            len: 1 //~ ERROR use of unstable library feature
+        }
+    };
+}
diff --git a/src/test/compile-fail/privacy-ufcs.rs b/src/test/compile-fail/privacy-ufcs.rs
new file mode 100644 (file)
index 0000000..ccb379c
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test to ensure private traits are inaccessible with UFCS angle-bracket syntax.
+
+mod foo {
+    trait Bar {
+        fn baz() {}
+    }
+
+    impl Bar for i32 {}
+}
+
+fn main() {
+    <i32 as ::foo::Bar>::baz(); //~ERROR method `baz` is inaccessible
+                                //~^NOTE: trait `Bar` is private
+}
diff --git a/src/test/compile-fail/pushpop-unsafe-rejects.rs b/src/test/compile-fail/pushpop-unsafe-rejects.rs
deleted file mode 100644 (file)
index 72c065a..0000000
+++ /dev/null
@@ -1,74 +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.
-
-// Basic sanity check for `push_unsafe!(EXPR)` and
-// `pop_unsafe!(EXPR)`: we can call unsafe code when there are a
-// positive number of pushes in the stack, or if we are within a
-// normal `unsafe` block, but otherwise cannot.
-
-#![feature(pushpop_unsafe)]
-
-static mut X: i32 = 0;
-
-unsafe fn f() { X += 1; return; }
-fn g() { unsafe { X += 1_000; } return; }
-
-fn main() {
-    push_unsafe!( {
-        f(); pop_unsafe!({
-            f() //~ ERROR: call to unsafe function
-        })
-    } );
-
-    push_unsafe!({
-        f();
-        pop_unsafe!({
-            g();
-            f(); //~ ERROR: call to unsafe function
-        })
-    } );
-
-    push_unsafe!({
-        g(); pop_unsafe!({
-            unsafe {
-                f();
-            }
-            f(); //~ ERROR: call to unsafe function
-        })
-    });
-
-
-    // Note: For implementation simplicity the compiler just
-    // ICE's if you underflow the push_unsafe stack.
-    //
-    // Thus all of the following cases cause an ICE.
-    //
-    // (The "ERROR" notes are from an earlier version
-    //  that used saturated arithmetic rather than checked
-    //  arithmetic.)
-
-    //    pop_unsafe!{ g() };
-    //
-    //    push_unsafe!({
-    //        pop_unsafe!(pop_unsafe!{ g() })
-    //    });
-    //
-    //    push_unsafe!({
-    //        g();
-    //        pop_unsafe!(pop_unsafe!({
-    //            f() // ERROR: call to unsafe function
-    //        }))
-    //    });
-    //
-    //    pop_unsafe!({
-    //        f(); // ERROR: call to unsafe function
-    //    })
-
-}
index b8c4a7f8a8c0555e2be24ab036cb96b4397795ef..ec0631a881a37bdaee81aaae3e1bcfd227f1d1f8 100644 (file)
@@ -37,7 +37,7 @@ pub struct WithHrAssoc<T>
 }
 
 fn with_assoc<'a,'b>() {
-    // We get an error because beacuse 'b:'a does not hold:
+    // We get an error because 'b:'a does not hold:
 
     let _: &'a WithHrAssoc<TheType<'b>> = loop { };
     //~^ ERROR reference has a longer lifetime
diff --git a/src/test/compile-fail/stability-attribute-sanity-2.rs b/src/test/compile-fail/stability-attribute-sanity-2.rs
new file mode 100644 (file)
index 0000000..cdeff7a
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// More checks that stability attributes are used correctly
+
+#![feature(staged_api)]
+#![staged_api]
+
+#[stable(feature = "a", feature = "b", since = "1.0.0")] //~ ERROR multiple 'feature' items
+fn f1() { }
+
+#[stable(feature = "a", sinse = "1.0.0")] //~ ERROR unknown meta item 'sinse'
+fn f2() { }
+
+#[unstable(feature = "a", issue = "no")] //~ ERROR incorrect 'issue'
+fn f3() { }
+
+fn main() { }
index 00c5be0f211e3d7b52e3bade9bf6c95008390fe4..f71e66ded7e621c9846e2d236c8eef23e358e619 100644 (file)
 #![staged_api]
 
 mod bogus_attribute_types_1 {
-    #[stable(feature = "a", since = "a", reason)] //~ ERROR incorrect meta item
+    #[stable(feature = "a", since = "a", reason)] //~ ERROR unknown meta item 'reason'
     fn f1() { }
 
-    #[stable(feature = "a", since, reason = "a")] //~ ERROR incorrect meta item
+    #[stable(feature = "a", since)] //~ ERROR incorrect meta item
     fn f2() { }
 
-    #[stable(feature, since = "a", reason = "a")] //~ ERROR incorrect meta item
+    #[stable(feature, since = "a")] //~ ERROR incorrect meta item
     fn f3() { }
 
-    #[stable(feature = "a", since = "a", reason(b))] //~ ERROR incorrect meta item
-    fn f4() { }
-
-    #[stable(feature = "a", since(b), reason = "a")] //~ ERROR incorrect meta item
+    #[stable(feature = "a", since(b))] //~ ERROR incorrect meta item
     fn f5() { }
 
-    #[stable(feature(b), since = "a", reason = "a")] //~ ERROR incorrect meta item
+    #[stable(feature(b), since = "a")] //~ ERROR incorrect meta item
     fn f6() { }
 }
 
@@ -56,11 +53,11 @@ mod bogus_attribute_types_2 {
 }
 
 mod missing_feature_names {
-    #[unstable(since = "a", issue = "0")] //~ ERROR missing 'feature'
+    #[unstable(issue = "0")] //~ ERROR missing 'feature'
     fn f1() { }
 
-    #[unstable(feature = "a")]
-    fn f2() { } //~ ERROR need to point to an issue
+    #[unstable(feature = "a")] //~ ERROR missing 'issue'
+    fn f2() { }
 
     #[stable(since = "a")] //~ ERROR missing 'feature'
     fn f3() { }
@@ -75,12 +72,12 @@ mod missing_version {
     fn f2() { }
 }
 
-#[unstable(feature = "a", since = "b", issue = "0")]
+#[unstable(feature = "a", issue = "0")]
 #[stable(feature = "a", since = "b")]
 fn multiple1() { } //~ ERROR multiple stability levels
 
-#[unstable(feature = "a", since = "b", issue = "0")]
-#[unstable(feature = "a", since = "b", issue = "0")]
+#[unstable(feature = "a", issue = "0")]
+#[unstable(feature = "a", issue = "0")]
 fn multiple2() { } //~ ERROR multiple stability levels
 
 #[stable(feature = "a", since = "b")]
@@ -88,12 +85,12 @@ fn multiple2() { } //~ ERROR multiple stability levels
 fn multiple3() { } //~ ERROR multiple stability levels
 
 #[stable(feature = "a", since = "b")]
-#[deprecated(since = "b")]
-#[deprecated(since = "b")]
+#[deprecated(since = "b", reason = "text")]
+#[deprecated(since = "b", reason = "text")]
 fn multiple4() { } //~ ERROR multiple deprecated attributes
 //~^ ERROR Invalid stability or deprecation version found
 
-#[deprecated(since = "a")]
+#[deprecated(since = "a", reason = "text")]
 fn deprecated_without_unstable_or_stable() { } //~ ERROR deprecated attribute must be paired
 
 fn main() { }
diff --git a/src/test/compile-fail/struct-no-fields-enumlike.rs b/src/test/compile-fail/struct-no-fields-enumlike.rs
new file mode 100644 (file)
index 0000000..6bdbae1
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+
+struct Foo(); //~ ERROR empty tuple structs and enum variants are not allowed
+
+fn main() {}
diff --git a/src/test/compile-fail/trait-not-accessible.rs b/src/test/compile-fail/trait-not-accessible.rs
new file mode 100644 (file)
index 0000000..21668fc
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod m {
+    trait Priv {
+        fn f(&self) {}
+    }
+    impl Priv for super::S {}
+    pub trait Pub: Priv {}
+}
+
+struct S;
+impl m::Pub for S {}
+
+fn g<T: m::Pub>(arg: T) {
+    arg.f(); //~ ERROR: source trait is private
+}
+
+fn main() {
+    g(S);
+}
index b11cbde292969018ae9ec870d9b2be0895ad83e9..13fe314fbcdd1cb5c9ab333ddb8c2f91ca0f1a36 100644 (file)
@@ -21,4 +21,5 @@ fn main() {
     //~^ ERROR E0038
     //~| ERROR E0038
     //~| ERROR E0277
+    //~| WARNING E0038
 }
index 918589b8fd3ac0f665d45b57e716d26f8234ff61..df87a7bbdc9c223eb877f372d3987a14f9ab5dee 100644 (file)
@@ -16,12 +16,12 @@ use std::mem::transmute;
 
 unsafe fn f() {
     let _: i8 = transmute(16i16);
-    //~^ ERROR transmute called on types with different sizes
+    //~^ ERROR transmute called with differently sized types
 }
 
 unsafe fn g<T>(x: &T) {
     let _: i8 = transmute(x);
-    //~^ ERROR transmute called on types with potentially different sizes
+    //~^ ERROR transmute called with differently sized types
 }
 
 fn main() {}
index 31456853e1c0f1543207f7c0776e36861700fe91..f7324247f3b4a01eb60a78a2206a0da461ab058e 100644 (file)
 use std::mem::transmute;
 
 fn a<T, U: ?Sized>(x: &[T]) -> &U {
-    unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes
+    unsafe { transmute(x) } //~ ERROR transmute called with differently sized types
 }
 
 fn b<T: ?Sized, U: ?Sized>(x: &T) -> &U {
-    unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes
+    unsafe { transmute(x) } //~ ERROR transmute called with differently sized types
 }
 
 fn c<T, U>(x: &T) -> &U {
@@ -31,11 +31,11 @@ fn d<T, U>(x: &[T]) -> &[U] {
 }
 
 fn e<T: ?Sized, U>(x: &T) -> &U {
-    unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes
+    unsafe { transmute(x) } //~ ERROR transmute called with differently sized types
 }
 
 fn f<T, U: ?Sized>(x: &T) -> &U {
-    unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes
+    unsafe { transmute(x) } //~ ERROR transmute called with differently sized types
 }
 
 fn main() { }
index a77a37a77e146c107a5dfc970709f7ea58deb579..55cebbd6cfcbe71ec8915bbd9e8ec4567c524b9e 100644 (file)
@@ -26,7 +26,7 @@ impl<T: ?Sized> Foo<T> {
 
     fn n(x: &T) -> &isize {
         // Not OK here, because T : Sized is not in scope.
-        unsafe { transmute(x) } //~ ERROR transmute called on types with potentially different sizes
+        unsafe { transmute(x) } //~ ERROR transmute called with differently sized types
     }
 }
 
index 2e076337f53ef7cceb00f2a3d0ba23a848164904..62db4c5d366d6e0ba7a4c7982b053cdf591ed487 100644 (file)
@@ -17,4 +17,3 @@ fn main() {
     //~^ ERROR mutating transmuted &mut T from &T may cause undefined behavior
 }
 
-
index 2dcd7a97d8977eec83fc37a53c8dd016bc3b31fa..23306823c729c0e7ab977d1de9636d7376950b16 100644 (file)
@@ -12,7 +12,7 @@
 
 use std::marker::PhantomData;
 
-// A erroneous variant of `run-pass/unboxed_closures-infer-recursive-fn.rs`
+// An erroneous variant of `run-pass/unboxed_closures-infer-recursive-fn.rs`
 // where we attempt to perform mutation in the recursive function. This fails to compile
 // because it winds up requiring `FnMut` which enforces linearity.
 
diff --git a/src/test/compile-fail/unsafe-const-fn.rs b/src/test/compile-fail/unsafe-const-fn.rs
new file mode 100644 (file)
index 0000000..24ac41c
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// A quick test of 'unsafe const fn' functionality
+
+#![feature(const_fn)]
+
+const unsafe fn dummy(v: u32) -> u32 {
+    !v
+}
+
+const VAL: u32 = dummy(0xFFFF); //~ ERROR E0133
+
+fn main() {
+    assert_eq!(VAL, 0xFFFF0000);
+}
+
diff --git a/src/test/compile-fail/useless-priv.rs b/src/test/compile-fail/useless-priv.rs
deleted file mode 100644 (file)
index 59964d0..0000000
+++ /dev/null
@@ -1,22 +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.
-
-struct A { pub i: isize }
-pub enum C { pub Variant }      //~ ERROR: unnecessary `pub`
-
-pub trait E {
-    fn foo(&self);
-}
-
-impl E for A {
-    pub fn foo(&self) {}             //~ ERROR: unnecessary visibility
-}
-
-fn main() {}
diff --git a/src/test/compile-fail/useless-pub.rs b/src/test/compile-fail/useless-pub.rs
new file mode 100644 (file)
index 0000000..fb6cdf7
--- /dev/null
@@ -0,0 +1,21 @@
+// 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.
+
+struct A { pub i: isize }
+
+pub trait E {
+    fn foo(&self);
+}
+
+impl E for A {
+    pub fn foo(&self) {}             //~ ERROR: unnecessary visibility
+}
+
+fn main() {}
index 319b81bde36ed02bb556fca7367e5ca80a6e49d8..bb452eecbfc8b3551522d1acab284f0e7a4feaaa 100644 (file)
@@ -48,7 +48,7 @@ struct Test5<'a, 'b:'a> { //~ ERROR regions=[[+, o];[];[]]
 
 // Invariance is a trap from which NO ONE CAN ESCAPE.
 // In other words, even though the `&'b isize` occurs in
-// a argument list (which is contravariant), that
+// an argument list (which is contravariant), that
 // argument list occurs in an invariant context.
 
 #[rustc_variance]
index 222d8338aa2c4c5ad0c282916cc039cdc9e9e2e5..b6f197987bab1df73c4b5a3552f229f36f9234a3 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(bivariance)]
 #![allow(dead_code)]
 #![feature(rustc_attrs)]
 
index e407ebe345a5b2e5f3ac6e21989b52803c991832..2fd8bf20c79974beef8c80e77077a1dd8dedf268 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(bivariance)]
 #![allow(dead_code)]
 #![feature(rustc_attrs)]
 
index 375289596841d5ae59474d5a80034f71ac5926e3..c8f4326bb28241a32531d13b70a2aed201c2a09b 100644 (file)
@@ -29,7 +29,6 @@ use std::cell::Cell;
 use id::Id;
 
 mod s {
-    #![allow(unstable)]
     use std::sync::atomic::{AtomicUsize, Ordering};
 
     static S_COUNT: AtomicUsize = AtomicUsize::new(0);
diff --git a/src/test/compile-fail/wf-method-late-bound-regions.rs b/src/test/compile-fail/wf-method-late-bound-regions.rs
new file mode 100644 (file)
index 0000000..b9d292f
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// A method's receiver must be well-formed, even if it has late-bound regions.
+// Because of this, a method's substs being well-formed does not imply that
+// the method's implied bounds are met.
+
+struct Foo<'b>(Option<&'b ()>);
+
+trait Bar<'b> {
+    fn xmute<'a>(&'a self, u: &'b u32) -> &'a u32;
+}
+
+impl<'b> Bar<'b> for Foo<'b> {
+    fn xmute<'a>(&'a self, u: &'b u32) -> &'a u32 { u }
+}
+
+fn main() {
+    let f = Foo(None);
+    let f2 = f;
+    let dangling = {
+        let pointer = Box::new(42);
+        f2.xmute(&pointer) //~ ERROR `pointer` does not live long enough
+    };
+    println!("{}", dangling);
+}
diff --git a/src/test/compile-fail/wf-misc-methods-issue-28609.rs b/src/test/compile-fail/wf-misc-methods-issue-28609.rs
new file mode 100644 (file)
index 0000000..055c86a
--- /dev/null
@@ -0,0 +1,84 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// check that misc. method calls are well-formed
+
+use std::marker::PhantomData;
+use std::ops::{Deref, Shl};
+
+#[derive(Copy, Clone)]
+struct S<'a, 'b: 'a> {
+    marker: PhantomData<&'a &'b ()>,
+    bomb: Option<&'b u32>
+}
+
+type S2<'a> = S<'a, 'a>;
+
+impl<'a, 'b> S<'a, 'b> {
+    fn transmute_inherent(&self, a: &'b u32) -> &'a u32 {
+        a
+    }
+}
+
+fn return_dangling_pointer_inherent(s: S2) -> &u32 {
+    let s = s;
+    s.transmute_inherent(&mut 42) //~ ERROR does not live long enough
+}
+
+impl<'a, 'b> Deref for S<'a, 'b> {
+    type Target = &'a u32;
+    fn deref(&self) -> &&'a u32 {
+        self.bomb.as_ref().unwrap()
+    }
+}
+
+fn return_dangling_pointer_coerce(s: S2) -> &u32 {
+    let four = 4;
+    let mut s = s;
+    s.bomb = Some(&four); //~ ERROR does not live long enough
+    &s
+}
+
+fn return_dangling_pointer_unary_op(s: S2) -> &u32 {
+    let four = 4;
+    let mut s = s;
+    s.bomb = Some(&four); //~ ERROR does not live long enough
+    &*s
+}
+
+impl<'a, 'b> Shl<&'b u32> for S<'a, 'b> {
+    type Output = &'a u32;
+    fn shl(self, t: &'b u32) -> &'a u32 { t }
+}
+
+fn return_dangling_pointer_binary_op(s: S2) -> &u32 {
+    let s = s;
+    s << &mut 3 //~ ERROR does not live long enough
+}
+
+fn return_dangling_pointer_method(s: S2) -> &u32 {
+    let s = s;
+    s.shl(&mut 3) //~ ERROR does not live long enough
+}
+
+fn return_dangling_pointer_ufcs(s: S2) -> &u32 {
+    let s = s;
+    S2::shl(s, &mut 3) //~ ERROR does not live long enough
+}
+
+fn main() {
+    let s = S { marker: PhantomData, bomb: None };
+    let _inherent_dp = return_dangling_pointer_inherent(s);
+    let _coerce_dp = return_dangling_pointer_coerce(s);
+    let _unary_dp = return_dangling_pointer_unary_op(s);
+    let _binary_dp = return_dangling_pointer_binary_op(s);
+    let _method_dp = return_dangling_pointer_method(s);
+    let _ufcs_dp = return_dangling_pointer_ufcs(s);
+}
diff --git a/src/test/compile-fail/wf-static-method.rs b/src/test/compile-fail/wf-static-method.rs
new file mode 100644 (file)
index 0000000..6c6522f
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// check that static methods don't get to assume their trait-ref
+// is well-formed.
+// FIXME(#27579): this is just a bug. However, our checking with
+// static inherent methods isn't quite working - need to
+// fix that before removing the check.
+
+trait Foo<'a, 'b, T>: Sized {
+    fn make_me() -> Self { loop {} }
+    fn static_evil(u: &'b u32) -> &'a u32;
+}
+
+struct Evil<'a, 'b: 'a>(Option<&'a &'b ()>);
+
+impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () {
+    fn make_me() -> Self { }
+    fn static_evil(u: &'b u32) -> &'a u32 {
+        u //~ ERROR cannot infer an appropriate lifetime
+    }
+}
+
+struct IndirectEvil<'a, 'b: 'a>(Option<&'a &'b ()>);
+
+impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> {
+    fn make_me() -> Self { IndirectEvil(None) }
+    fn static_evil(u: &'b u32) -> &'a u32 {
+        let me = Self::make_me(); //~ ERROR lifetime bound not satisfied
+        loop {} // (`me` could be used for the lifetime transmute).
+    }
+}
+
+impl<'a, 'b> Evil<'a, 'b> {
+    fn inherent_evil(u: &'b u32) -> &'a u32 {
+        u //~ ERROR cannot infer an appropriate lifetime
+    }
+}
+
+// while static methods don't get to *assume* this, we still
+// *check* that they hold.
+
+fn evil<'a, 'b>(b: &'b u32) -> &'a u32 {
+    <()>::static_evil(b) //~ ERROR cannot infer an appropriate lifetime
+}
+
+fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 {
+    <IndirectEvil>::static_evil(b)
+    //~^ ERROR cannot infer an appropriate lifetime
+}
+
+fn inherent_evil<'a, 'b>(b: &'b u32) -> &'a u32 {
+    <Evil>::inherent_evil(b) // bug? shouldn't this be an error
+}
+
+
+fn main() {}
index d203806c08dcac2f8699237e1e1388c3f50fdc58..ebaad663bb4e74488f4c2f635a9bc0c0efd178b1 100644 (file)
@@ -80,6 +80,7 @@
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 trait TraitWithAssocType {
index 1aabd549ca59506d8330cd52d1a2be91a47df7ba..8818063ddf4ba5cfec43812d94bef3f612707c5d 100644 (file)
@@ -44,6 +44,7 @@
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 // N.B. These are `mut` only so they don't constant fold away.
index f0c187fd223781fa1e80f6d4ee4b731f9589c930..ccf9508a3856ccd53e2f5cb85d22434bf4d6b996 100644 (file)
@@ -49,6 +49,7 @@
 // gdb-command:continue
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 // N.B. These are `mut` only so they don't constant fold away.
index 3b662ae0264fbff85ef9d9f2208754d1fc783c5d..1a6b605d9d06aef1d91f9e78285aa02eb5617718 100644 (file)
@@ -64,6 +64,7 @@
 // gdb-command:continue
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn main() {
index 4094c2e9b133928ff14a770d8433adab863c0570..4ebd0c95770299430d9de1f44761be4409f12b3f 100644 (file)
@@ -82,6 +82,7 @@
 // gdb-check:$28 = 9.25
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 static mut B: bool = false;
index c9144b18b2fe811827d1de86ad5f47aaf4b2a75f..998010832881b1e2b99be2457c751486f9ad3ef7 100644 (file)
@@ -87,6 +87,7 @@
 // lldb-check:[...]$12 = 3.5
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn main() {
index b0f06bb8a758c3ecabfd8502fd1d461c49a07aee..bada77b66293c6011c17ed01dca5443882df1d47 100644 (file)
 // lldb-check:[...]$12 = 3.5
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn main() {
index ecc70f4d77e2ff4afdd460869797a354af30dc93..c80783ef310686b6c3f425faa2ed7280cb113bc9 100644 (file)
@@ -40,6 +40,7 @@
 // lldb-check:[...]$2 = TheC
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 enum ABC { TheA, TheB, TheC }
index 732383b5e4008ff71b8e2eda685581ebf861714b..b21574e32866b66d9daca6780bc83e974b523fb5 100644 (file)
@@ -39,6 +39,7 @@
 // lldb-check:[...]$2 = TheOnlyCase(4820353753753434)
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 // The first element is to ensure proper alignment, irrespective of the machines word size. Since
index 70c24fc2ab07bf6a47acdfea1b0f2252ec29d8b5..ab41185cb7391671873dbfb21281403d56a2c615 100644 (file)
@@ -64,6 +64,7 @@
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct SomeStruct {
index add9bdceadab015174f443a09684d40958522074..e3da3934f6d696de39fbb11bcc77a697da6296f8 100644 (file)
@@ -42,6 +42,7 @@
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn main() {
@@ -49,7 +50,7 @@ fn main() {
     let stack_val_ref: &(i16, f32) = &stack_val;
     let ref_to_unnamed: &(i16, f32) = &(-15, -20f32);
 
-    let unique_val: Box<(i16, f32)> = box() (-17, -22f32);
+    let unique_val: Box<(i16, f32)> = box (-17, -22f32);
     let unique_val_ref: &(i16, f32) = &*unique_val;
 
     zzz(); // #break
index d8ce3af478911a27c4a655936a57b19fbb44efca..88af94c53628c0b99ed9f857be74d26a18966252 100644 (file)
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn main() {
index e5f4306b24b047c3fa6f9b89fb94f95b4c251c6a..106d0b243eb2608c7107243b93d143ec87adda0e 100644 (file)
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn main() {
     let a = box 1;
-    let b = box() (2, 3.5f64);
+    let b = box (2, 3.5f64);
 
     zzz(); // #break
 }
index 9c6e197e65e23ebd495db0996f15fe8ed50c762e..dd543405e4c27d1070cfcf98e5201360aaf536a1 100644 (file)
@@ -35,6 +35,7 @@
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct StructWithSomePadding {
index 1e89d0e31b86af31c33c194ae6d6dfd608901d62..a329ef6d0e0908c3a4622094bb593d11c7218261 100644 (file)
@@ -70,6 +70,7 @@
 // lldb-check:[...]$6 = Case1 { x: 0, y: 8970181431921507452 }
 // lldb-command:continue
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 #[derive(Clone)]
index 39da48f9e7a7616451c500b79d5cd3e6fe900d8b..a768bfdd16764f4be950c047764741db964f564f 100644 (file)
@@ -45,6 +45,7 @@
 // lldb-check:[...]$2 = (4444.5, 5555, 6666, 7777.5)
 // lldb-command:continue
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 trait Trait {
index 562b0d588f5cacb0865a4d55c028e85392bdb736..83a22edc96fe1ff74c0ceccb004abd864ed5ea9e 100644 (file)
@@ -64,6 +64,7 @@
 // lldb-check:[...]$6 = (StructWithDrop { a: OneHundred, b: Vienna }, 9)
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 use self::AnEnum::{OneHundred, OneThousand, OneMillion};
index 3024ca0fe69834142d101a102f98f220876f6228..4eec26d335c44d3eee3752ba0ca6bf6a6995824c 100644 (file)
@@ -99,6 +99,7 @@
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 use self::AutoDiscriminant::{One, Two, Three};
index 448e157a251b211494910338d7a26a639e0c5ff1..5335e0bfa4a6984297f7449e3da158962850b19a 100644 (file)
@@ -46,6 +46,7 @@
 // lldb-command:continue
 
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn some_generic_fun<T1, T2>(a: T1, b: T2) -> (T2, T1) {
index ec5a6fa3d3f16e0dc0e6e9d04ac84e14faa5fb0f..04e19b30fd414242ed0014298a4aca5672308bd7 100644 (file)
@@ -13,6 +13,7 @@
 // compile-flags:-g
 
 #![allow(dead_code, unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 #![feature(const_fn)]
 #![feature(static_mutex)]
index 785778e62f6eadafbe94c2e77142691450faadc3..fb40400a4429cfe3a1ca496b5d16c8d26da08745 100644 (file)
@@ -13,6 +13,7 @@
 // compile-flags:-g
 
 #![allow(dead_code, unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 // This test makes sure that the compiler doesn't crash when trying to assign
index ce6ef080c1f11955850346b3daf8a960cabca0b5..544fe2c66d5e802123be3a95271e070e15738ee8 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 // min-lldb-version: 310
@@ -20,7 +21,7 @@ extern crate cross_crate_spans;
 
 // === GDB TESTS ===================================================================================
 
-// gdb-command:break cross_crate_spans.rs:23
+// gdb-command:break cross_crate_spans.rs:24
 // gdb-command:run
 
 // gdb-command:print result
@@ -43,7 +44,7 @@ extern crate cross_crate_spans;
 
 // === LLDB TESTS ==================================================================================
 
-// lldb-command:b cross_crate_spans.rs:23
+// lldb-command:b cross_crate_spans.rs:24
 // lldb-command:run
 
 // lldb-command:print result
index 5d330e16a13e4e11e45932bc14a282ecec1000b3..954a7abe6323cbddef769a9164838f5ec1832393 100644 (file)
 #![allow(unused_variables)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 use self::Univariant::Unit;
@@ -432,7 +433,7 @@ fn main() {
     managed_box(&(34, 35));
     borrowed_pointer(&(36, 37));
     contained_borrowed_pointer((&38, 39));
-    unique_pointer(box() (40, 41, 42));
+    unique_pointer(box (40, 41, 42));
     ref_binding((43, 44, 45));
     ref_binding_in_tuple((46, (47, 48)));
     ref_binding_in_struct(Struct { a: 49, b: 50 });
index ad04f97fb08a2d14c683489dc4c62e2728b6b437..a34d5d6adbfcbb412b1389e91da45d7ee262eeeb 100644 (file)
 #![allow(unused_variables)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct Struct {
index 632f17bd2007b2761390535bc513df7456f7039c..a43e4546d4f8f86c5af18eff12c71b4d493adfd6 100644 (file)
 #![allow(unused_variables)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 use self::Univariant::Unit;
@@ -303,7 +304,7 @@ fn main() {
     let (&cc, _) = (&38, 39);
 
     // unique pointer
-    let box dd = box() (40, 41, 42);
+    let box dd = box (40, 41, 42);
 
     // ref binding
     let ref ee = (43, 44, 45);
index 1a9b9f73cba999964d61e3cec3b998a57047219c..8624a0cba02568f14fd399780691e600b2f5a677 100644 (file)
@@ -50,6 +50,7 @@
 // lldb-check:[...]$4 = StructPaddedAtEnd { x: [22, 23], y: [24, 25] }
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct NoPadding1 {
index 9e73417e7de7400843f334df0fb081849c12c06e..c93db41dc55bf640aef4b4ff61d9c45d922c7904 100644 (file)
@@ -44,6 +44,7 @@
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 
index a1ca59caa3304008e638380cb13c2f4c1390371b..d007b507556188f4f5bc6c6dec1c7f89b9bf70a0 100644 (file)
 
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn immediate_args(a: isize, b: bool, c: f64) {
index 21c2cc09a9fd4f91019895676599b6d0bb7c4569..c8f2e385a6e74fbac0dd2d4393743004d900678f 100644 (file)
@@ -45,6 +45,7 @@
 // lldb-command:continue
 
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn main() {
index d9cca5eb315177cdae7bfde277d015a4c92fdda1..b5b6ca7572703cc65fab869385623d0d4b924be5 100644 (file)
 // lldb-command:continue
 
 #![allow(dead_code, unused_assignments, unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 #[no_stack_check]
index b34f1af01f5fd35b76bfda019fdcf9569737b016..529a8cd635a921e00a2d2ae6f73123a76c740e51 100644 (file)
 // lldb-command:continue
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn immediate_args(a: isize, b: bool, c: f64) {
index ae290e228cc4ab81d78469b8e259fc47fd86d5ca..3115b3f7e761c219b02528e1139b443f5925cddf 100644 (file)
@@ -62,6 +62,7 @@
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 // This test case makes sure that we get correct type descriptions for the enum
index 890133c58c8938a9a274527a96cc12420e8f0653..415dd36212a44786fe19de0d97f26f5259786239 100644 (file)
@@ -69,6 +69,7 @@
 // lldb-check:[...]$8 = ((5, Struct { a: 6, b: 7.5 }), (Struct { a: 6, b: 7.5 }, 5))
 // lldb-command:continue
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 #[derive(Clone)]
index 5f9236038b22eb16aec03d49c10aefdebfa2bceb..79ae007a5006285820e37cc016dd47216911095c 100644 (file)
@@ -70,6 +70,7 @@
 // lldb-command:continue
 
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn outer<TA: Clone>(a: TA) {
index 14df15242dfdeab0f6e9cb7e56fa75af16c5b3ba..968cb2e15971630d1b3324c11d2623bd39ebac18 100644 (file)
 // lldb-command:continue
 
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 #[derive(Copy, Clone)]
index f24b221ccec2c4caae433dfc8e54570bbcd29ff8..603365089ecef89ead86dcc3e4f15ed080d93f22 100644 (file)
@@ -31,6 +31,7 @@
 // gdb-command:continue
 
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct Struct {
index caed4bd181d64ab2d649052d75e74375cea89cae..991404f56eff96da531c93a8c98d690e76ef8a77 100644 (file)
@@ -29,6 +29,7 @@
 // gdb-check:$4 = {{a = -1}}
 
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 use self::Regular::{Case1, Case2, Case3};
index a459badfa8a3c2f1ebbeda73ad5226ffbe2a5ac6..92a67a2344d1c8909d35666fb2b006841f3dbe5c 100644 (file)
@@ -41,6 +41,7 @@
 // lldb-check:[...]$3 = AGenericStruct<f64, generic_struct::AGenericStruct<i32, f64>> { key: 6.5, value: AGenericStruct<i32, f64> { key: 7, value: 8.5 } }
 
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct AGenericStruct<TKey, TValue> {
index 83340c83dc01c6bf7fdb1f1e4563f9d80a5efd95..e2727fbe7df4a426454cac5382ebb9f02ffe8f59 100644 (file)
@@ -47,6 +47,7 @@
 // lldb-command:print univariant
 // lldb-check:[...]$3 = TheOnlyCase(-1)
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 use self::Regular::{Case1, Case2, Case3};
index 1dead6c2734f886e82c502029aa7b8d6a44e2760..2c75349e5c8c7b18c8252ca26bc6c0b38a5d97d2 100644 (file)
@@ -35,6 +35,7 @@
 // lldb-command:continue
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 // This test case makes sure that debug info does not ICE when include_str is
index b259efc9caf804cac305122f01517fad8434c125..c30ee92dc532df9ef79254b2e4541bab3e01dcd6 100644 (file)
 
 // gdb-command:run
 // gdb-command:next
-// gdb-check:[...]34[...]s
+// gdb-check:[...]35[...]s
 // gdb-command:continue
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 // IF YOU MODIFY THIS FILE, BE CAREFUL TO ADAPT THE LINE NUMBERS IN THE DEBUGGER COMMANDS
index af518797d19df1f2ea56fa12d9dc7d004046666f..a971e06ed5ec211b4a94f3a461802ffd80027059 100644 (file)
@@ -30,6 +30,7 @@
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct ZeroSizedStruct;
index dceb436310fa3a3d0aded48d7f3ac49e1b2494bf..e99e241411bfd3a56e83103bb71fc87bf07ea49f 100644 (file)
@@ -85,6 +85,7 @@
 // lldb-check:[...]$6 = 1000000
 // lldb-command:continue
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn main() {
index 08a762fc4e5d8bd4af196ee2557affc0dbfad190..42e288321e1977366dc266b3701831558a1d4d73 100644 (file)
 // lldb-check:[...]$15 = -1
 // lldb-command:continue
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn main() {
index 228799848c64667371627443841557f7095def69..597d9837aadcffb3e5571fac494ad60e4596497a 100644 (file)
 // lldb-check:[...]$17 = 232
 // lldb-command:continue
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct Struct {
index c0b65fbb22b53bc6dba2666e3d189b1efc2687da..0a8d3b61a8d8db681aad922b0e89a6f475d705ce 100644 (file)
@@ -69,6 +69,7 @@
 // lldb-check:[...]$5 = false
 // lldb-command:continue
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn main() {
index 868cea29a7bc3d4ebb7ca3b6f7d41dc36d97db61..e55088afd7d9fc739e2c21fcd06482d0159591c5 100644 (file)
 // lldb-check:[...]$12 = 2
 // lldb-command:continue
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn main() {
index 5bae2aa7ae2cc14dde3bd697347e713a5ce227e0..70dece865ece02fd36a64a5cede9d9e8fc157172 100644 (file)
@@ -70,6 +70,7 @@
 // lldb-command:continue
 
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn main() {
index b5f43e7d21f1a1f6b928ac75ba9523c95ec2f730..38d8b75a644fd2d825d8e681d5e3e5baa0ae60aa 100644 (file)
 // lldb-check:[...]$12 = 2
 // lldb-command:continue
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn main() {
index 1dd738c6d512e8b410738c4c69f04b5c74d9f2d0..a00d0f74f1e4e45771e9d166c1b8fae1f8cbdb7c 100644 (file)
 // lldb-command:continue
 
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 macro_rules! trivial {
index 1d406af10a21564a5193dfe6edbedcbacd64b46d..841786f930daf11da743fd74ecc39aa4ee49957d 100644 (file)
 
 #![allow(unused_variables)]
 #![allow(unused_assignments)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 static mut MUT_INT: isize = 0;
index ea7d150164dfb6efc082e85a17e49dc6c6a5821e..3d21def3953b802fdffcf0d951060b53558448bc 100644 (file)
@@ -29,6 +29,7 @@
 
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct Struct {
index 77a11db8ba4dbcdf37cfe413ee223f3370975a77..6437b3bb900f8d16787297e054fbdd4c3dc4d67c 100644 (file)
 // lldb-command:continue
 
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 #[derive(Copy, Clone)]
index f76f8c8cad2d3f2fb1bcc28456a77569aba3319a..5b697f859d4edc6d666b06cf76a2e77ee0837759 100644 (file)
 
 
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 #[derive(Copy, Clone)]
index 28885d0ad9b79828bd10b5638242babaef775081..3bf2e775e779147c3a89562faa298e6dd51a7bbb 100644 (file)
 
 
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 #[derive(Copy, Clone)]
index b69a3856736c4521d8677d5331fc1230462487a3..5ce4a7905a1d0da61521ad74c841747d12ee3de6 100644 (file)
 
 
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 #[derive(Copy, Clone)]
index 4ea0fd44475c29ca238f7f2727577ab172564be6..d8644a3934f102b4d46dccceb6d85e61c168a9ec 100644 (file)
 
 
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 #[derive(Copy, Clone)]
index 5fe0c13e5e4a5a198c35394e2ba9d9967ba16cc5..71ba1bcea306a1fac71d64832bd03342e851cf37 100644 (file)
@@ -44,6 +44,7 @@
 // lldb-check:[...]$2 = 30303
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn function_one() {
index 3179a8050d35d1cee49c129eaa775c1fadb2511e..7a1b7b19d9f5d1cc5db9d95f3306a268226754eb 100644 (file)
@@ -44,6 +44,7 @@
 // lldb-check:[...]$2 = 30303
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn function_one() {
index 5553d7e496b57eefa705f23c3519dd8905b53bf0..462e1c59aea227929d1ea40698dc911925fa4db5 100644 (file)
@@ -93,6 +93,7 @@
 // lldb-check:[...]$11 = 20
 // lldb-command:continue
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn main() {
index 44d7c2b1ad23e00076b5c958980b22af681676b4..81399ec590b14cedf235f21e12ea64313ee5c866 100644 (file)
@@ -22,6 +22,7 @@
 // gdb-check:$2 = {<No data fields>}
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 enum ANilEnum {}
index f39e8ee222932e1cf1a9557ca3f3d41cfeee5c37..6bdd68d5e26e557b8b4d43489e302b6844476a99 100644 (file)
@@ -23,6 +23,8 @@
 // gdb-command:continue
 
 #![allow(unused_variables)]
+#![feature(no_debug)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn function_with_debuginfo() {
index fba21d9a553ba80d7c341ac83170f7e274fd1a29..f103294a94a07f9166de6e49047b1c696742096f 100644 (file)
@@ -79,6 +79,7 @@
 // lldb-check:[...]$9 = Nope
 
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 // If a struct has exactly two variants, one of them is empty, and the other one
index 8b2f34a99099c5d088b321125858ff4c5a96785e..9d37cb3012b7de923eb8a2a78e6365c27ed91cd2 100644 (file)
@@ -73,6 +73,7 @@
 
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 #[repr(packed)]
index 9f3b7baf83db2c7c37c5b3e86d42cfa019b2dd5c..e86e963f38cdd4adb3a7680510335e6f81689663 100644 (file)
@@ -59,6 +59,7 @@
 // lldb-check:[...]$5 = 40
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 #[repr(packed)]
index ef1092efa11455a565c4c3a0f93e4c86daf4d3a7..3094bdeac8b66592a1c3cb68e68b583deb0b5992 100644 (file)
@@ -17,6 +17,7 @@
 // is taken from issue #11083.
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 pub struct Window<'a> {
index 4772ee10ff7243c550374a5a09de06211af8f082..ea067d5bffbec8f152a72b3a152ac5f3672560cb 100644 (file)
@@ -69,6 +69,7 @@
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 use self::Opt::{Empty, Val};
index f16f236a0cb0612750600331e838bb786e0d03d1..6d3f93c5d5014ae14640377be36f1051d9d449d4 100644 (file)
 // lldb-command:continue
 
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 #[derive(Copy, Clone)]
index 56de877016deebdb3d42b22de9abe7b872c199be..aea3bae4bfc1b0b4aa2de89f857a6123050c9c99 100644 (file)
 // lldb-command:continue
 
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 #[derive(Copy, Clone)]
index 4d74e6f1084e5a7a012e79c09f387d45a9f2adeb..baf782b7e678a182f67613cd1daff1b6f1fc91d3 100644 (file)
@@ -58,6 +58,7 @@
 // lldb-command:continue
 
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn a_function(x: bool, y: bool) {
index 630999677ab1b3a3c1f628a5febbdfdb07b82beb..4883853f72fce1d1abc9860a7da447a1ab5549c1 100644 (file)
@@ -57,6 +57,7 @@
 // lldb-check:[...]$5 = 20
 // lldb-command:continue
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn main() {
index 6bc8892a83a6939cc497505522f720a978106f3b..24eb407612c3e514669b12e4104559fd5ad2d091 100644 (file)
@@ -41,6 +41,7 @@
 // gdb-command:continue
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 #![feature(core_simd)]
 
index c1dae7a6d677c3f89b5fa794af1caefa2ec2ae7d..5f9a4fd08053404d685e708d876db3bb490a064c 100644 (file)
@@ -78,6 +78,7 @@
 // lldb-command:continue
 
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn main() {
index 36007c1093297e14ba015b3eb5f3047cb8659ca0..d25cd4d7c047f5675c215346df45aa33fa46a1e1 100644 (file)
@@ -96,6 +96,7 @@
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct NoPadding16 {
index 29bf9c5e419fdb439cc53648b017d7bd95d34ce4..1b85ecc537a3450fc4031a185255cfde9b7e6a7f 100644 (file)
@@ -91,6 +91,7 @@
 
 #![allow(unused_variables)]
 #![allow(dead_code)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 static mut NO_PADDING_8: (i8, u8) = (-50, 50);
index 59fe96f99580e9d1d44fc4cefef3356cb077a9d6..dab4ab515d9954e4c931f5462b69b1fac776825d 100644 (file)
@@ -53,6 +53,7 @@
 // lldb-check:[...]$4 = 5
 // lldb-command:continue
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct Struct {
index e200a497f51c2c7d944b863e1ea0f52708de25e2..98b90de60051691be0931fc852c43722673188b0 100644 (file)
@@ -41,6 +41,7 @@
 // lldb-check:[...]$2 = TheOnlyCase(Struct { x: 123, y: 456, z: 789 })
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 use self::Regular::{Case1, Case2};
index 8bccb041c9a90d2b9648e6d14eb4195b76e4c761..76a1613c2314699f08e0d576f6542a4df725bcbd 100644 (file)
@@ -56,6 +56,7 @@
 // lldb-check:[...]$7 = Tree { x: Simple { x: 25 }, y: InternalPaddingParent { x: InternalPadding { x: 26, y: 27 }, y: InternalPadding { x: 28, y: 29 }, z: InternalPadding { x: 30, y: 31 } }, z: BagInBag { x: Bag { x: Simple { x: 32 } } } }
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct Simple {
index 43cb48d16bf4b8cb6e8e11f554b9ed43aa42263c..3376fc9bbd450f76425efd77e20c6cf28cb1376e 100644 (file)
@@ -48,6 +48,7 @@
 // lldb-check:[...]$3 = TheOnlyCase { a: -1 }
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 use self::Regular::{Case1, Case2, Case3};
index 4c2c9d06ae91caac150ba37849aa7687e5a33340..ad8731997abd738509f2fa7ae536c24aaa5f89ef 100644 (file)
@@ -44,6 +44,7 @@
 // lldb-check:[...]$3 = NestedOuter { a: NestedInner { a: WithDestructor { x: 7890, y: 9870 } } }
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct NoDestructor {
index 3054f646b91009d28bf646be5df2a1efe2f73a19..193cd419bab882341a6daf7d7ac1e5d4e36eba38 100644 (file)
@@ -16,6 +16,7 @@
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 trait Trait {
index 04119956f1944de89fc170a26edadfb7c94a6176..1a7fde766f0d808c773d9f43b25dd11cdd19a538 100644 (file)
@@ -42,6 +42,7 @@
 // gdb-check:$10 = {x = {__0 = {__0 = 40, __1 = 41, __2 = 42}, __1 = {__0 = 43, __1 = 44}}, y = {__0 = 45, __1 = 46, __2 = 47, __3 = 48}}
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct NoPadding1 {
index e98109130311b09de503f3c5c5a61314916d2768..a514b69a2d31d067e7f8c6b72cc49251f06da267 100644 (file)
@@ -56,6 +56,7 @@
 // lldb-check:[...]$6 = ((21, 22), 23)
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 fn main() {
index 5e4e8494574463c46b6f71960d060be1e56dade8..a2ca8c2237b428205738e1540c4a4b6e40fa20cf 100644 (file)
@@ -62,6 +62,7 @@
 // structs.
 
 
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct NoPadding16(u16, i16);
index 48c47c51150deefc7220aa4cdb8dd2520180add8..52f171434b037942d5da0a86ff1bd96f5905341f 100644 (file)
@@ -48,6 +48,7 @@
 // lldb-check:[...]$3 = TheOnlyCase(-1)
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 use self::Regular::{Case1, Case2, Case3};
index 4eae074120233fd5e121f8e9c972e031edb6f59e..3db3e9d311da09a640ea0e51d89e20e7610cad63 100644 (file)
 
 #![feature(box_syntax)]
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 use self::Enum1::{Variant1, Variant2};
index 0252e3b54fff30b4aea1a64218d0bb29321d330c..bbf13ec756ad81394b0a78451ad8ce89e8329e0f 100644 (file)
@@ -42,6 +42,7 @@
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 // The first element is to ensure proper alignment, irrespective of the machines word size. Since
index 63536b1383475be0889ea6b93bb21a572f6ccb74..4c4210ea132a666279c70b560ae186a4d12f0766 100644 (file)
@@ -13,6 +13,7 @@
 // compile-flags:-g
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 // No need to actually run the debugger, just make sure that the compiler can
index d576aff8b1c08319b3bdbb1d1712f38439155c4f..7090377e5db1bfd7fbdf23f51e3f492cd40116bd 100644 (file)
@@ -79,6 +79,7 @@
 
 #![allow(unused_variables)]
 #![feature(box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct Struct {
index 2b27f938b308f7a1b937d8e224d4870e11af88c2..aa269edadd8f410b9a96b40e1e965e38f5124c43 100644 (file)
@@ -41,6 +41,7 @@
 
 #![allow(unused_variables)]
 #![feature(unboxed_closures, box_syntax)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct Struct {
index 54ef42b48f1b1d8c070c9b6c367075480534f117..6def5cf285934f7790f334ccbf06960eb902fd39 100644 (file)
@@ -71,6 +71,7 @@
 
 #![feature(unboxed_closures, box_syntax)]
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct Struct {
index 87fd2e9a65d031b3401b5626c15c73274d2bc603..0d396c885eb85f2efbad184cc3e3ee9846702d04 100644 (file)
@@ -77,6 +77,7 @@
 // lldb-check:[...]$5 = &[AStruct { x: 10, y: 11, z: 12 }, AStruct { x: 13, y: 14, z: 15 }]
 
 #![allow(dead_code, unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 struct AStruct {
index f7bdf1bd3faafa33ec6c03923ce7e71183b987f1..c9827a02fc759fe65b8e487b65ef3b1389a898ae 100644 (file)
@@ -28,6 +28,7 @@
 // lldb-check:[...]$0 = [1, 2, 3]
 
 #![allow(unused_variables)]
+#![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
 
 static mut VECT: [i32; 3] = [1, 2, 3];
diff --git a/src/test/parse-fail/lifetime-in-pattern.rs b/src/test/parse-fail/lifetime-in-pattern.rs
new file mode 100644 (file)
index 0000000..8802497
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn test(&'a str) {
+    //~^ ERROR unexpected lifetime `'a` in pattern
+}
+
+fn main() {
+}
diff --git a/src/test/parse-fail/parenthesized-box-expr-message.rs b/src/test/parse-fail/parenthesized-box-expr-message.rs
deleted file mode 100644 (file)
index 3cf3685..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z parse-only
-
-fn main() {
-    box (1 + 1)
-    //~^ HELP try using `box ()` instead:
-    //~| SUGGESTION box () (1 + 1)
-    //~| WARN deprecated syntax
-    ; //~ ERROR expected expression, found `;`
-}
diff --git a/src/test/parse-fail/struct-no-fields-2.rs b/src/test/parse-fail/struct-no-fields-2.rs
deleted file mode 100644 (file)
index 1e6169f..0000000
+++ /dev/null
@@ -1,20 +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.
-
-// compile-flags: -Z parse-only
-
-struct Foo;
-
-fn f2() {
-    let _end_stmt     = Foo { };
-    //~^ ERROR: structure literal must either have at least one field
-}
-
-fn main() {}
diff --git a/src/test/parse-fail/struct-no-fields-3.rs b/src/test/parse-fail/struct-no-fields-3.rs
deleted file mode 100644 (file)
index 8e72151..0000000
+++ /dev/null
@@ -1,20 +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.
-
-// compile-flags: -Z parse-only
-
-struct Foo;
-
-fn g3() {
-    let _mid_tuple    = (Foo { }, 2);
-    //~^ ERROR: structure literal must either have at least one field
-}
-
-fn main() {}
diff --git a/src/test/parse-fail/struct-no-fields-4.rs b/src/test/parse-fail/struct-no-fields-4.rs
deleted file mode 100644 (file)
index 6e55baf..0000000
+++ /dev/null
@@ -1,20 +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.
-
-// compile-flags: -Z parse-only
-
-struct Foo;
-
-fn h4() {
-    let _end_of_tuple = (3, Foo { });
-    //~^ ERROR: structure literal must either have at least one field
-}
-
-fn main() {}
diff --git a/src/test/parse-fail/struct-no-fields-5.rs b/src/test/parse-fail/struct-no-fields-5.rs
deleted file mode 100644 (file)
index 5f92d98..0000000
+++ /dev/null
@@ -1,20 +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.
-
-// compile-flags: -Z parse-only
-
-struct Foo;
-
-fn i5() {
-    let _end_of_block = { Foo { } };
-    //~^ ERROR: structure literal must either have at least one field
-}
-
-fn main() {}
diff --git a/src/test/parse-fail/struct-no-fields-enumlike.rs b/src/test/parse-fail/struct-no-fields-enumlike.rs
deleted file mode 100644 (file)
index 19a3958..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z parse-only
-
-struct Foo(); //~ ERROR unit-like struct definition should be written as `struct Foo;`
-
-fn main() {}
diff --git a/src/test/parse-fail/struct-no-fields.rs b/src/test/parse-fail/struct-no-fields.rs
deleted file mode 100644 (file)
index fa5065b..0000000
+++ /dev/null
@@ -1,16 +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.
-
-// compile-flags: -Z parse-only
-
-struct Foo {}
-//~^ ERROR: unit-like struct definition should be written as `struct Foo;`
-
-fn main() {}
diff --git a/src/test/parse-fail/struct-variant-no-fields.rs b/src/test/parse-fail/struct-variant-no-fields.rs
deleted file mode 100644 (file)
index 68cf661..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z parse-only
-
-enum Foo {
-    Bar {} //~ ERROR unit-like struct variant should be written without braces, as `Bar,`
-}
index 6398c76d0a351dca8856a93ede20c621510e6331..835f7fc96c63fb5e9c6ef6976b32a63daab8a945 100644 (file)
@@ -27,10 +27,9 @@ pub fn bar() {
     let _: [(); (1 as usize)] = ([(() as ())] as [(); 1]);
 
     let _ =
-        (((&((([(1 as i32), (2 as i32), (3 as i32)] as [i32; 3])) as [i32; 3])
-              as &[i32; 3]) as *const _ as *const [i32; 3]) as
-            *const [i32; (3 as usize)] as *const [i32; 3]);
-
+        (((&([(1 as i32), (2 as i32), (3 as i32)] as [i32; 3]) as &[i32; 3])
+             as *const _ as *const [i32; 3]) as *const [i32; (3 as usize)] as
+            *const [i32; 3]);
 
 
 
index 0b82a0d8d837816848902c00fc000e45bba58708..e326949458ebf86fe43ded57c79ec0a2d8bd853f 100644 (file)
@@ -11,7 +11,7 @@
 // error-pattern:stop
 
 // #18576
-// Make sure that an calling extern function pointer in an unreachable
+// Make sure that calling an extern function pointer in an unreachable
 // context doesn't cause an LLVM assertion
 
 #[allow(unreachable_code)]
diff --git a/src/test/run-fail/issue-28934.rs b/src/test/run-fail/issue-28934.rs
new file mode 100644 (file)
index 0000000..2f437c7
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test: issue had to do with "givens" in region inference,
+// which were not being considered during the contraction phase.
+
+// error-pattern:explicit panic
+
+struct Parser<'i: 't, 't>(&'i u8, &'t u8);
+
+impl<'i, 't> Parser<'i, 't> {
+    fn parse_nested_block<F, T>(&mut self, parse: F) -> Result<T, ()>
+        where for<'tt> F: FnOnce(&mut Parser<'i, 'tt>) -> T { panic!() }
+
+    fn expect_exhausted(&mut self) -> Result<(), ()> { Ok(()) }
+}
+
+fn main() {
+    let x = 0u8;
+    Parser(&x, &x).parse_nested_block(|input| input.expect_exhausted()).unwrap();
+}
index cd13b817c2b8c5fc6d7f2ac64257bff0b3b1db6d..6c6a41fa6f2e3e6deaa21b8e62bcb2faa94b8959 100644 (file)
@@ -11,9 +11,7 @@
 // error-pattern:thread '<main>' panicked at 'arithmetic operation overflowed'
 // compile-flags: -C debug-assertions
 
-// (Work around constant-evaluation)
-fn value() -> u8 { 200 }
 
 fn main() {
-    let _x = value() + value() + value();
+    let _x = 200u8 + 200u8 + 200u8;
 }
index 54159153382084a239a90c033b7d33100b639a1d..62935bacce8711f90b198d14fc5b7b387f1f53bc 100644 (file)
@@ -11,9 +11,8 @@
 // error-pattern:thread '<main>' panicked at 'shift operation overflowed'
 // compile-flags: -C debug-assertions
 
-// (Work around constant-evaluation)
-fn id<T>(x: T) -> T { x }
+#![warn(exceeding_bitshifts)]
 
 fn main() {
-    let _x = 1_i32 << id(32);
+    let _x = 1_i32 << 32;
 }
index fd3e801457c2359912fe3ce1680796b25d137520..f6e6cb105c51bd797fa12c0ae5cef393e8fe726d 100644 (file)
@@ -11,9 +11,8 @@
 // error-pattern:thread '<main>' panicked at 'shift operation overflowed'
 // compile-flags: -C debug-assertions
 
-// (Work around constant-evaluation)
-fn id<T>(x: T) -> T { x }
+#![warn(exceeding_bitshifts)]
 
 fn main() {
-    let _x = 1 << id(-1);
+    let _x = 1 << -1;
 }
index 58914bab3fb15e248dee3dbf4e21d0035ce63b42..a70f31954c6edaf65d7331f6eff2199679f1d4d5 100644 (file)
@@ -11,9 +11,8 @@
 // error-pattern:thread '<main>' panicked at 'shift operation overflowed'
 // compile-flags: -C debug-assertions
 
-// (Work around constant-evaluation)
-fn id<T>(x: T) -> T { x }
+#![warn(exceeding_bitshifts)]
 
 fn main() {
-    let _x = 1_u64 << id(64);
+    let _x = 1_u64 << 64;
 }
index ed25876cec47906c061767cdff910e5cdc24bbf8..571feaeb94345f70b2de1103fa3db812f922a65b 100644 (file)
 // This function is checking that our automatic truncation does not
 // sidestep the overflow checking.
 
-// (Work around constant-evaluation)
-fn id<T>(x: T) -> T { x }
+#![warn(exceeding_bitshifts)]
 
 fn main() {
     // this signals overflow when checking is on
-    let x = 1_i8 << id(17);
+    let x = 1_i8 << 17;
 
     // ... but when checking is off, the fallback will truncate the
     // input to its lower three bits (= 1). Note that this is *not*
index 5d2f53962406c5427793320805a0b068ef75c40e..a413a6f0abfa29d489fdac600e5f05a6cace1c2d 100644 (file)
@@ -11,9 +11,6 @@
 // error-pattern:thread '<main>' panicked at 'arithmetic operation overflowed'
 // compile-flags: -C debug-assertions
 
-// (Work around constant-evaluation)
-fn value() -> u8 { 200 }
-
 fn main() {
-    let x = value() * 4;
+    let x = 200u8 * 4;
 }
index cdb74c7d7e2610ecce3ea003216f65b88683f74a..7891d1ce9bed4931d2bd8fb7cd6e2256b5a61115 100644 (file)
@@ -11,9 +11,6 @@
 // error-pattern:thread '<main>' panicked at 'attempted to negate with overflow'
 // compile-flags: -C debug-assertions
 
-// (Work around constant-evaluation)
-fn value() -> i8 { std::i8::MIN }
-
 fn main() {
-    let _x = -value();
+    let _x = -std::i8::MIN;
 }
index c36a16f18f86e963ee0a7e57d2a9b2397b61e069..b58eaf7f836c2c2e1d38ad48d16159ef9c7f8059 100644 (file)
@@ -11,9 +11,8 @@
 // error-pattern:thread '<main>' panicked at 'shift operation overflowed'
 // compile-flags: -C debug-assertions
 
-// (Work around constant-evaluation)
-fn id<T>(x: T) -> T { x }
+#![warn(exceeding_bitshifts)]
 
 fn main() {
-    let _x = -1_i32 >> id(32);
+    let _x = -1_i32 >> 32;
 }
index f619ebe9fb4a60ca9241d15f3133f2a420b9b739..40b468a6ad41974d4b50b5c943b48e7d21eeefa2 100644 (file)
@@ -11,9 +11,8 @@
 // error-pattern:thread '<main>' panicked at 'shift operation overflowed'
 // compile-flags: -C debug-assertions
 
-// (Work around constant-evaluation)
-fn id<T>(x: T) -> T { x }
+#![warn(exceeding_bitshifts)]
 
 fn main() {
-    let _x = -1_i32 >> id(-1);
+    let _x = -1_i32 >> -1;
 }
index c261e195fd71ebe3b39d72f35418aa05446639fc..afe6a908cb5f13587dee7d6d6dd564e1081009fd 100644 (file)
@@ -11,9 +11,8 @@
 // error-pattern:thread '<main>' panicked at 'shift operation overflowed'
 // compile-flags: -C debug-assertions
 
-// (Work around constant-evaluation)
-fn id<T>(x: T) -> T { x }
+#![warn(exceeding_bitshifts)]
 
 fn main() {
-    let _x = -1_i64 >> id(64);
+    let _x = -1_i64 >> 64;
 }
index 6e79a13d4e133ba93deb5ca86a3c8e449b60fa7c..585186575f6eda614bd4631861624bd1205e5387 100644 (file)
 // This function is checking that our (type-based) automatic
 // truncation does not sidestep the overflow checking.
 
-// (Work around constant-evaluation)
-fn id<T>(x: T) -> T { x }
+#![warn(exceeding_bitshifts)]
 
 fn main() {
     // this signals overflow when checking is on
-    let x = 2_i8 >> id(17);
+    let x = 2_i8 >> 17;
 
     // ... but when checking is off, the fallback will truncate the
     // input to its lower three bits (= 1). Note that this is *not*
index b089dccbaa52f0c54b18abcb4ec65377ccd0c383..ece4d37c36eb31171ca1fa40009cb51f6893e0e5 100644 (file)
@@ -11,9 +11,6 @@
 // error-pattern:thread '<main>' panicked at 'arithmetic operation overflowed'
 // compile-flags: -C debug-assertions
 
-// (Work around constant-evaluation)
-fn value() -> u8 { 42 }
-
 fn main() {
-    let _x = value() - (value() + 1);
+    let _x = 42u8 - (42u8 + 1);
 }
diff --git a/src/test/run-make/allow-non-lint-warnings-cmdline/1 b/src/test/run-make/allow-non-lint-warnings-cmdline/1
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/src/test/run-make/allow-warnings-cmdline-stability/1 b/src/test/run-make/allow-warnings-cmdline-stability/1
deleted file mode 100644 (file)
index e69de29..0000000
index 72c2d389e2aac7cf9beb1426568f50d33b88b002..5202e6dea541ee396c97d99c249d7cbce84fccca 100644 (file)
@@ -3,8 +3,8 @@
 all:
        mkdir $(TMPDIR)/a
        mkdir $(TMPDIR)/b
-       $(CC) -c -o $(TMPDIR)/a/foo.o foo.c
-       $(CC) -c -o $(TMPDIR)/b/foo.o bar.c
+       $(call COMPILE_OBJ,$(TMPDIR)/a/foo.o,foo.c)
+       $(call COMPILE_OBJ,$(TMPDIR)/b/foo.o,bar.c)
        ar crus $(TMPDIR)/libfoo.a $(TMPDIR)/a/foo.o $(TMPDIR)/b/foo.o
        $(RUSTC) foo.rs
        $(RUSTC) bar.rs
index 97d09c837c10acde0db7c53ef21a30e39ff5345b..baa4c1c0237b25573e52921cda167ec51bc1db65 100644 (file)
@@ -1,4 +1,6 @@
 -include ../tools.mk
 
 all:
-       $(rustc) -o foo foo.rs
+       cp foo.rs $(TMPDIR)
+       cd $(TMPDIR) && $(RUSTC) -o foo foo.rs
+       $(call RUN,foo)
index 113717a776a99f8f533c6d77622170a747568e35..a97554935412332df45cf1a7ddf47334770780ea 100644 (file)
@@ -1,2 +1,5 @@
 // ignore-license
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
 int foo() { return 0; }
index 113717a776a99f8f533c6d77622170a747568e35..b2849326a7588583aaea7f7badaff2abb855e174 100644 (file)
@@ -1,2 +1,6 @@
 // ignore-license
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
 int foo() { return 0; }
index 2a6cc0394852e1708464c31953ca8076e555fa0e..7b2130cd4ed96bdc2dc402c67b677da4907bdfe5 100644 (file)
@@ -1,10 +1,17 @@
 -include ../tools.mk
 
-HOST_LIB_DIR=$(TMPDIR)/../../../stage$(RUST_BUILD_STAGE)/lib
-
-all:
-       $(RUSTC) foo.rs
-       $(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) $(call RPATH_LINK_SEARCH,$(HOST_LIB_DIR)) -Wl,-rpath,$(TMPDIR) $(EXTRACFLAGS)
+all: $(TMPDIR)/$(call BIN,bar)
        $(call RUN,bar)
        $(call REMOVE_DYLIBS,foo)
        $(call FAIL,bar)
+
+ifdef IS_MSVC
+$(TMPDIR)/$(call BIN,bar): $(call DYLIB,foo)
+       $(CC) bar.c $(TMPDIR)/foo.lib $(call OUT_EXE,bar)
+else
+$(TMPDIR)/$(call BIN,bar): $(call DYLIB,foo)
+       $(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) -L $(TMPDIR)
+endif
+
+$(call DYLIB,foo): foo.rs
+       $(RUSTC) foo.rs
index 2b927e3e4a730835bebe04f11dd0f37f2c10b104..3d44b3c256efcaa4da06c40f260b2f88fd0e88ac 100644 (file)
@@ -1,12 +1,12 @@
 -include ../tools.mk
 
-EXTRAFLAGS := $(EXTRACFLAGS)
-
 # FIXME: ignore freebsd
 ifneq ($(shell uname),FreeBSD)
 all:
        $(RUSTC) foo.rs
-       $(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) $(EXTRAFLAGS) $(EXTRACXXFLAGS)
+       cp $(TMPDIR)/libfoo.a $(call NATIVE_STATICLIB,foo2)
+       $(CC) bar.c $(call NATIVE_STATICLIB,foo2) $(call OUT_EXE,bar) \
+               $(EXTRACFLAGS) $(EXTRACXXFLAGS)
        $(call RUN,bar)
        rm $(call STATICLIB,foo*)
        $(call RUN,bar)
index 9914e12d5696e6561c108ef3794562bfaa589ff1..f88786857ccdc26bd247f326fffc2c349d4b9bb7 100644 (file)
@@ -1,9 +1,9 @@
 -include ../tools.mk
 
-all: $(call STATICLIB,cfoo)
+all: $(call NATIVE_STATICLIB,cfoo)
        $(RUSTC) foo.rs -C prefer-dynamic
        $(RUSTC) bar.rs
-       rm $(TMPDIR)/$(call STATICLIB_GLOB,cfoo)
+       rm $(call NATIVE_STATICLIB,cfoo)
        $(call RUN,bar)
        $(call REMOVE_DYLIBS,foo)
        $(call FAIL,bar)
index 02b24ef9846dd48cc9048b5f6b6463e35c3f6a69..be22b2728f05b0eca8e1a1e4d82cc86b8b2ba80d 100644 (file)
@@ -1,8 +1,8 @@
 -include ../tools.mk
 
-all: $(call STATICLIB,cfoo)
+all: $(call NATIVE_STATICLIB,cfoo)
        $(RUSTC) foo.rs
        $(RUSTC) bar.rs
        $(call REMOVE_RLIBS,foo)
-       rm $(TMPDIR)/$(call STATICLIB_GLOB,cfoo)
+       rm $(call NATIVE_STATICLIB,cfoo)
        $(call RUN,bar)
diff --git a/src/test/run-make/compile-stdin/Makefile b/src/test/run-make/compile-stdin/Makefile
new file mode 100644 (file)
index 0000000..1442224
--- /dev/null
@@ -0,0 +1,5 @@
+-include ../tools.mk
+
+all:
+       echo 'fn main(){}' | $(RUSTC) -
+       $(call RUN,rust_out)
index 2fe518324336171c97d0c4bfb37e314979fafd39..17ecb33ab28d0124e3a11891a493e786c0eeab74 100644 (file)
@@ -7,5 +7,5 @@ all:
        rm $(TMPDIR)/$(call BIN,bar)
        $(RUSTC) foo1.rs
        rm $(TMPDIR)/$(call BIN,foo)
-       $(RUSTC) foo1.rs -o $(TMPDIR)/bar1
+       $(RUSTC) foo1.rs -o $(TMPDIR)/$(call BIN,bar1)
        rm $(TMPDIR)/$(call BIN,bar1)
index a1828cd1f5d731d5319808bee97afdc3b71335f2..9b79d1af5218164ce4d1d10cbee0283a19a83ff3 100644 (file)
@@ -7,9 +7,10 @@
 ifneq ($(shell uname),FreeBSD)
 ifndef IS_WINDOWS
 all:
-       $(RUSTC) --emit dep-info,link --crate-type=lib lib.rs
+       cp *.rs $(TMPDIR)
+       $(RUSTC) --emit dep-info,link --crate-type=lib $(TMPDIR)/lib.rs
        sleep 2
-       touch foo.rs
+       touch $(TMPDIR)/foo.rs
        -rm -f $(TMPDIR)/done
        $(MAKE) -drf Makefile.foo
        sleep 2
@@ -17,6 +18,11 @@ all:
        pwd
        $(MAKE) -drf Makefile.foo
        rm $(TMPDIR)/done && exit 1 || exit 0
+
+       # When a source file is deleted `make` should still work
+       rm $(TMPDIR)/bar.rs
+       cp $(TMPDIR)/lib2.rs $(TMPDIR)/lib.rs
+       $(MAKE) -drf Makefile.foo
 else
 all:
 
diff --git a/src/test/run-make/dep-info/lib2.rs b/src/test/run-make/dep-info/lib2.rs
new file mode 100644 (file)
index 0000000..1b70fb4
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+
+#![crate_name = "foo"]
+
+pub mod foo;
index a7c6f5225a6526506ce8bd321b4912cda2bc5a8c..f4031a3aaae1cc3621f02558d54cdbfed45feca7 100644 (file)
@@ -31,7 +31,7 @@ use rustc::middle::ty;
 use rustc::session::config::{self, basic_options, build_configuration, Input, Options};
 use rustc::session::build_session;
 use rustc_driver::driver;
-use rustc_front::lowering::lower_crate;
+use rustc_front::lowering::{lower_crate, LoweringContext};
 use rustc_resolve::MakeGlobMap;
 use libc::c_void;
 
@@ -223,12 +223,13 @@ fn compile_program(input: &str, sysroot: PathBuf)
             .expect("phase_2 returned `None`");
 
         let krate = driver::assign_node_ids(&sess, krate);
-        let mut hir_forest = ast_map::Forest::new(lower_crate(&krate));
+        let lcx = LoweringContext::new(&sess, Some(&krate));
+        let mut hir_forest = ast_map::Forest::new(lower_crate(&lcx, &krate));
         let arenas = ty::CtxtArenas::new();
         let ast_map = driver::make_map(&sess, &mut hir_forest);
 
         driver::phase_3_run_analysis_passes(
-            sess, ast_map, &krate, &arenas, id, MakeGlobMap::No, |tcx, analysis| {
+            &sess, ast_map, &arenas, &id, MakeGlobMap::No, |tcx, analysis| {
 
             let trans = driver::phase_4_translate_to_llvm(tcx, analysis);
 
@@ -246,7 +247,7 @@ fn compile_program(input: &str, sysroot: PathBuf)
             let modp = llmod as usize;
 
             (modp, deps)
-        }).1
+        })
     }).unwrap();
 
     match handle.join() {
index a325acbf687b54d01868aded39450f79a904fe3e..cf897dba1f2798ba4944b6523eeba7c1def1b9cf 100644 (file)
@@ -1,8 +1,6 @@
 -include ../tools.mk
 
-all:
-       $(CC) -std=c99 test.c -c -o $(TMPDIR)/test.o
-       $(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o
-       $(RUSTC) testcrate.rs -L $(TMPDIR)
-       $(RUSTC) test.rs -L $(TMPDIR)
+all: $(call NATIVE_STATICLIB,test)
+       $(RUSTC) testcrate.rs
+       $(RUSTC) test.rs
        $(call RUN,test) || exit 1
index ea6971853fe998aa42fc23e3d7421f300a71ef9f..042048ec25f63c05096693257dff6b2d8f6a3a2d 100644 (file)
@@ -1,7 +1,5 @@
 -include ../tools.mk
 
-all:
-       $(CC) -std=c99 test.c -c -o $(TMPDIR)/test.o
-       $(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o
-       $(RUSTC) test.rs -L $(TMPDIR)
+all: $(call NATIVE_STATICLIB,test)
+       $(RUSTC) test.rs
        $(call RUN,test) || exit 1
diff --git a/src/test/run-make/extern-fn-struct-passing-abi/Makefile b/src/test/run-make/extern-fn-struct-passing-abi/Makefile
new file mode 100644 (file)
index 0000000..042048e
--- /dev/null
@@ -0,0 +1,5 @@
+-include ../tools.mk
+
+all: $(call NATIVE_STATICLIB,test)
+       $(RUSTC) test.rs
+       $(call RUN,test) || exit 1
diff --git a/src/test/run-make/extern-fn-struct-passing-abi/test.c b/src/test/run-make/extern-fn-struct-passing-abi/test.c
new file mode 100644 (file)
index 0000000..4253767
--- /dev/null
@@ -0,0 +1,260 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#include <assert.h>
+#include <stdint.h>
+
+struct Rect {
+    int32_t a;
+    int32_t b;
+    int32_t c;
+    int32_t d;
+};
+
+struct BiggerRect {
+    struct Rect s;
+    int32_t a;
+    int32_t b;
+};
+
+struct FloatRect {
+    int32_t a;
+    int32_t b;
+    double c;
+};
+
+struct Huge {
+    int32_t a;
+    int32_t b;
+    int32_t c;
+    int32_t d;
+    int32_t e;
+};
+
+// System V x86_64 ABI:
+// a, b, c, d, e should be in registers
+// s should be byval pointer
+//
+// Win64 ABI:
+// a, b, c, d should be in registers
+// e should be on the stack
+// s should be byval pointer
+void byval_rect(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e, struct Rect s) {
+    assert(a == 1);
+    assert(b == 2);
+    assert(c == 3);
+    assert(d == 4);
+    assert(e == 5);
+    assert(s.a == 553);
+    assert(s.b == 554);
+    assert(s.c == 555);
+    assert(s.d == 556);
+}
+
+// System V x86_64 ABI:
+// a, b, c, d, e, f should be in registers
+// s should be byval pointer on the stack
+//
+// Win64 ABI:
+// a, b, c, d should be in registers
+// e, f should be on the stack
+// s should be byval pointer on the stack
+void byval_many_rect(int32_t a, int32_t b, int32_t c, int32_t d, int32_t e,
+                     int32_t f, struct Rect s) {
+    assert(a == 1);
+    assert(b == 2);
+    assert(c == 3);
+    assert(d == 4);
+    assert(e == 5);
+    assert(f == 6);
+    assert(s.a == 553);
+    assert(s.b == 554);
+    assert(s.c == 555);
+    assert(s.d == 556);
+}
+
+// System V x86_64 ABI:
+// a, b, c, d, e, f, g should be in sse registers
+// s should be split across 2 registers
+// t should be byval pointer
+//
+// Win64 ABI:
+// a, b, c, d should be in sse registers
+// e, f, g should be on the stack
+// s should be on the stack (treated as 2 i64's)
+// t should be on the stack (treated as an i64 and a double)
+void byval_rect_floats(float a, float b, double c, float d, float e,
+                       float f, double g, struct Rect s, struct FloatRect t) {
+    assert(a == 1.);
+    assert(b == 2.);
+    assert(c == 3.);
+    assert(d == 4.);
+    assert(e == 5.);
+    assert(f == 6.);
+    assert(g == 7.);
+    assert(s.a == 553);
+    assert(s.b == 554);
+    assert(s.c == 555);
+    assert(s.d == 556);
+    assert(t.a == 3489);
+    assert(t.b == 3490);
+    assert(t.c == 8.);
+}
+
+// System V x86_64 ABI:
+// a, b, d, e, f should be in registers
+// c passed via sse registers
+// s should be byval pointer
+//
+// Win64 ABI:
+// a, b, d should be in registers
+// c passed via sse registers
+// e, f should be on the stack
+// s should be byval pointer
+void byval_rect_with_float(int32_t a, int32_t b, float c, int32_t d,
+                           int32_t e, int32_t f, struct Rect s) {
+    assert(a == 1);
+    assert(b == 2);
+    assert(c == 3.);
+    assert(d == 4);
+    assert(e == 5);
+    assert(f == 6);
+    assert(s.a == 553);
+    assert(s.b == 554);
+    assert(s.c == 555);
+    assert(s.d == 556);
+}
+
+// System V x86_64 & Win64 ABI:
+// a, b should be in registers
+// s should be split across 2 integer registers
+void split_rect(int32_t a, int32_t b, struct Rect s) {
+    assert(a == 1);
+    assert(b == 2);
+    assert(s.a == 553);
+    assert(s.b == 554);
+    assert(s.c == 555);
+    assert(s.d == 556);
+}
+
+// System V x86_64 & Win64 ABI:
+// a, b should be in sse registers
+// s should be split across integer & sse registers
+void split_rect_floats(float a, float b, struct FloatRect s) {
+    assert(a == 1.);
+    assert(b == 2.);
+    assert(s.a == 3489);
+    assert(s.b == 3490);
+    assert(s.c == 8.);
+}
+
+// System V x86_64 ABI:
+// a, b, d, f should be in registers
+// c, e passed via sse registers
+// s should be split across 2 registers
+//
+// Win64 ABI:
+// a, b, d should be in registers
+// c passed via sse registers
+// e, f should be on the stack
+// s should be on the stack (treated as 2 i64's)
+void split_rect_with_floats(int32_t a, int32_t b, float c,
+                            int32_t d, float e, int32_t f, struct Rect s) {
+    assert(a == 1);
+    assert(b == 2);
+    assert(c == 3.);
+    assert(d == 4);
+    assert(e == 5.);
+    assert(f == 6);
+    assert(s.a == 553);
+    assert(s.b == 554);
+    assert(s.c == 555);
+    assert(s.d == 556);
+}
+
+// System V x86_64 & Win64 ABI:
+// a, b, c should be in registers
+// s should be split across 2 registers
+// t should be a byval pointer
+void split_and_byval_rect(int32_t a, int32_t b, int32_t c, struct Rect s, struct Rect t) {
+    assert(a == 1);
+    assert(b == 2);
+    assert(c == 3);
+    assert(s.a == 553);
+    assert(s.b == 554);
+    assert(s.c == 555);
+    assert(s.d == 556);
+    assert(t.a == 553);
+    assert(t.b == 554);
+    assert(t.c == 555);
+    assert(t.d == 556);
+}
+
+// System V x86_64 & Win64 ABI:
+// a, b should in registers
+// s and return should be split across 2 registers
+struct Rect split_ret_byval_struct(int32_t a, int32_t b, struct Rect s) {
+    assert(a == 1);
+    assert(b == 2);
+    assert(s.a == 553);
+    assert(s.b == 554);
+    assert(s.c == 555);
+    assert(s.d == 556);
+    return s;
+}
+
+// System V x86_64 & Win64 ABI:
+// a, b, c, d should be in registers
+// return should be in a hidden sret pointer
+// s should be a byval pointer
+struct BiggerRect sret_byval_struct(int32_t a, int32_t b, int32_t c, int32_t d, struct Rect s) {
+    assert(a == 1);
+    assert(b == 2);
+    assert(c == 3);
+    assert(d == 4);
+    assert(s.a == 553);
+    assert(s.b == 554);
+    assert(s.c == 555);
+    assert(s.d == 556);
+
+    struct BiggerRect t;
+    t.s = s; t.a = 27834; t.b = 7657;
+    return t;
+}
+
+// System V x86_64 & Win64 ABI:
+// a, b should be in registers
+// return should be in a hidden sret pointer
+// s should be split across 2 registers
+struct BiggerRect sret_split_struct(int32_t a, int32_t b, struct Rect s) {
+    assert(a == 1);
+    assert(b == 2);
+    assert(s.a == 553);
+    assert(s.b == 554);
+    assert(s.c == 555);
+    assert(s.d == 556);
+
+    struct BiggerRect t;
+    t.s = s; t.a = 27834; t.b = 7657;
+    return t;
+}
+
+// System V x86_64 & Win64 ABI:
+// s should be byval pointer (since sizeof(s) > 16)
+// return should in a hidden sret pointer
+struct Huge huge_struct(struct Huge s) {
+    assert(s.a == 5647);
+    assert(s.b == 5648);
+    assert(s.c == 5649);
+    assert(s.d == 5650);
+    assert(s.e == 5651);
+
+    return s;
+}
diff --git a/src/test/run-make/extern-fn-struct-passing-abi/test.rs b/src/test/run-make/extern-fn-struct-passing-abi/test.rs
new file mode 100644 (file)
index 0000000..b91362b
--- /dev/null
@@ -0,0 +1,98 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Passing structs via FFI should work regardless of whether
+// they get passed in multiple registers, byval pointers or the stack
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+#[repr(C)]
+struct Rect {
+    a: i32,
+    b: i32,
+    c: i32,
+    d: i32
+}
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+#[repr(C)]
+struct BiggerRect {
+    s: Rect,
+    a: i32,
+    b: i32
+}
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+#[repr(C)]
+struct FloatRect {
+    a: i32,
+    b: i32,
+    c: f64
+}
+
+#[derive(Clone, Copy, Debug, PartialEq)]
+#[repr(C)]
+struct Huge {
+    a: i32,
+    b: i32,
+    c: i32,
+    d: i32,
+    e: i32
+}
+
+#[link(name = "test", kind = "static")]
+extern {
+    fn byval_rect(a: i32, b: i32, c: i32, d: i32, e: i32, s: Rect);
+
+    fn byval_many_rect(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, s: Rect);
+
+    fn byval_rect_floats(a: f32, b: f32, c: f64, d: f32, e: f32,
+                         f: f32, g: f64, s: Rect, t: FloatRect);
+
+    fn byval_rect_with_float(a: i32, b: i32, c: f32, d: i32, e: i32, f: i32, s: Rect);
+
+    fn split_rect(a: i32, b: i32, s: Rect);
+
+    fn split_rect_floats(a: f32, b: f32, s: FloatRect);
+
+    fn split_rect_with_floats(a: i32, b: i32, c: f32, d: i32, e: f32, f: i32, s: Rect);
+
+    fn split_and_byval_rect(a: i32, b: i32, c: i32, s: Rect, t: Rect);
+
+    fn split_ret_byval_struct(a: i32, b: i32, s: Rect) -> Rect;
+
+    fn sret_byval_struct(a: i32, b: i32, c: i32, d: i32, s: Rect) -> BiggerRect;
+
+    fn sret_split_struct(a: i32, b: i32, s: Rect) -> BiggerRect;
+
+    fn huge_struct(s: Huge) -> Huge;
+}
+
+fn main() {
+    let s = Rect { a: 553, b: 554, c: 555, d: 556 };
+    let t = BiggerRect { s: s, a: 27834, b: 7657 };
+    let u = FloatRect { a: 3489, b: 3490, c: 8. };
+    let v = Huge { a: 5647, b: 5648, c: 5649, d: 5650, e: 5651 };
+
+    unsafe {
+        byval_rect(1, 2, 3, 4, 5, s);
+        byval_many_rect(1, 2, 3, 4, 5, 6, s);
+        byval_rect_floats(1., 2., 3., 4., 5., 6., 7., s, u);
+        byval_rect_with_float(1, 2, 3.0, 4, 5, 6, s);
+        split_rect(1, 2, s);
+        split_rect_floats(1., 2., u);
+        split_rect_with_floats(1, 2, 3.0, 4, 5.0, 6, s);
+        split_and_byval_rect(1, 2, 3, s, s);
+        split_rect(1, 2, s);
+        assert_eq!(huge_struct(v), v);
+        assert_eq!(split_ret_byval_struct(1, 2, s), s);
+        assert_eq!(sret_byval_struct(1, 2, 3, 4, s), t);
+        assert_eq!(sret_split_struct(1, 2, s), t);
+    }
+}
index ea6971853fe998aa42fc23e3d7421f300a71ef9f..042048ec25f63c05096693257dff6b2d8f6a3a2d 100644 (file)
@@ -1,7 +1,5 @@
 -include ../tools.mk
 
-all:
-       $(CC) -std=c99 test.c -c -o $(TMPDIR)/test.o
-       $(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o
-       $(RUSTC) test.rs -L $(TMPDIR)
+all: $(call NATIVE_STATICLIB,test)
+       $(RUSTC) test.rs
        $(call RUN,test) || exit 1
index 121e48e84e46fd8ba2fbbbbf1eb32c99f4859a37..506954fca46172efde81f8e1fd5b79ac11667ebd 100644 (file)
@@ -1,11 +1,21 @@
 // ignore-license
 // Pragma needed cause of gcc bug on windows: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991
+
+#ifdef _MSC_VER
+#pragma pack(push,1)
+struct Foo {
+    char a;
+    short b;
+    char c;
+};
+#else
 #pragma pack(1)
 struct __attribute__((packed)) Foo {
     char a;
     short b;
     char c;
 };
+#endif
 
 struct Foo foo(struct Foo foo) {
     return foo;
index a325acbf687b54d01868aded39450f79a904fe3e..cf897dba1f2798ba4944b6523eeba7c1def1b9cf 100644 (file)
@@ -1,8 +1,6 @@
 -include ../tools.mk
 
-all:
-       $(CC) -std=c99 test.c -c -o $(TMPDIR)/test.o
-       $(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o
-       $(RUSTC) testcrate.rs -L $(TMPDIR)
-       $(RUSTC) test.rs -L $(TMPDIR)
+all: $(call NATIVE_STATICLIB,test)
+       $(RUSTC) testcrate.rs
+       $(RUSTC) test.rs
        $(call RUN,test) || exit 1
index cf7683479f08e648341db30acada9f0988dcd6e7..1268022e37b744294eb2772f96333598109f9e33 100644 (file)
@@ -8,7 +8,7 @@
 # correct to complete the linkage. If passed as "-lfoo -lbar", then the 'foo'
 # library will be stripped out, and the linkage will fail.
 
-all: $(call STATICLIB,foo) $(call STATICLIB,bar)
+all: $(call NATIVE_STATICLIB,foo) $(call NATIVE_STATICLIB,bar)
        $(RUSTC) foo.rs
        $(RUSTC) bar.rs
        $(RUSTC) main.rs -Z print-link-args
diff --git a/src/test/run-make/invalid-staticlib/Makefile b/src/test/run-make/invalid-staticlib/Makefile
new file mode 100644 (file)
index 0000000..d4aa6d5
--- /dev/null
@@ -0,0 +1,5 @@
+-include ../tools.mk
+
+all:
+       touch $(TMPDIR)/libfoo.a
+       echo | $(RUSTC) - --crate-type=rlib -lstatic=foo 2>&1 | grep "failed to add native library"
diff --git a/src/test/run-make/issue-12446/Makefile b/src/test/run-make/issue-12446/Makefile
deleted file mode 100644 (file)
index e864ee0..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
--include ../tools.mk
-
-all: $(call STATICLIB,foo)
-       $(RUSTC) foo.rs
-       $(RUSTC) bar.rs
-       $(call RUN,bar)
diff --git a/src/test/run-make/issue-12446/bar.rs b/src/test/run-make/issue-12446/bar.rs
deleted file mode 100644 (file)
index cd41058..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-extern crate foo;
-
-#[link(name = "foo")]
-extern {}
-
-fn main() {
-    foo::foo();
-}
diff --git a/src/test/run-make/issue-12446/foo.c b/src/test/run-make/issue-12446/foo.c
deleted file mode 100644 (file)
index 186a004..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-// ignore-license
-void some_c_symbol() {}
diff --git a/src/test/run-make/issue-12446/foo.rs b/src/test/run-make/issue-12446/foo.rs
deleted file mode 100644 (file)
index 11c6116..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![crate_type = "rlib"]
-
-extern {
-    fn some_c_symbol();
-}
-
-pub fn foo() {
-    unsafe { some_c_symbol() }
-}
index 6ea3cf48ffbbd41d2d3179b81a3cb81eecbde1d2..bd94db09520288c593995cd866c8f043435f6223 100644 (file)
@@ -13,5 +13,5 @@ endif
 all:
        $(RUSTC) foo.rs --crate-type=rlib
        $(RUSTC) bar.rs --crate-type=staticlib -C lto -L. -o $(TMPDIR)/libbar.a
-       $(CC) foo.c -lbar -o $(call RUN_BINFILE,foo) $(EXTRACFLAGS)
+       $(CC) foo.c $(TMPDIR)/libbar.a $(EXTRACFLAGS) $(call OUT_EXE,foo)
        $(call RUN,foo)
diff --git a/src/test/run-make/issue-14698/Makefile b/src/test/run-make/issue-14698/Makefile
new file mode 100644 (file)
index 0000000..28502f6
--- /dev/null
@@ -0,0 +1,4 @@
+-include ../tools.mk
+
+all:
+       TMP=fake TMPDIR=fake $(RUSTC) foo.rs 2>&1 | grep "couldn't create a temp dir:"
diff --git a/src/test/run-make/issue-14698/foo.rs b/src/test/run-make/issue-14698/foo.rs
new file mode 100644 (file)
index 0000000..7dc79f2
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {}
index bc5e9b728694f27225af3f353dd192d6d7fa5068..846805686a12a82a8598b24a7e14fd17b00f1c7b 100644 (file)
@@ -1,6 +1,6 @@
 -include ../tools.mk
 
-all: $(TMPDIR)/libfoo.a
+all: $(call NATIVE_STATICLIB,foo)
        $(RUSTC) foo.rs -C extra-filename=-383hf8 -C prefer-dynamic
        $(RUSTC) bar.rs
        $(call RUN,bar)
index 2895ad473bf966158015a0295e161767b673f29a..fdf595b574e3397280431138651de0bfd5c85c6f 100644 (file)
@@ -1,2 +1,6 @@
 // ignore-license
+
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
 void foo() {}
index 6917fa55579801da9e10c8fc76b3a83257303340..8b96fe36824715b3197e36ee72f5cd3e595cac55 100644 (file)
@@ -8,9 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(linked_from)]
 #![crate_type = "dylib"]
 
 #[link(name = "foo", kind = "static")]
+#[linked_from = "foo"]
 extern {
     pub fn foo();
 }
index 8745cbecf913704df7cfa2c17631bb243b79a8a3..bd8c735df31a9f9a324a74f74a13fc1db6acf75a 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(rustc_private, path, convert)]
+#![feature(rustc_private)]
 
 extern crate rustc;
 extern crate rustc_driver;
@@ -16,7 +16,7 @@ extern crate rustc_lint;
 extern crate syntax;
 
 use rustc::session::{build_session, Session};
-use rustc::session::config::{basic_options, build_configuration, Input, OutputTypeExe};
+use rustc::session::config::{basic_options, build_configuration, Input, OutputType};
 use rustc_driver::driver::{compile_input, CompileController};
 use syntax::diagnostics::registry::Registry;
 
@@ -46,7 +46,7 @@ fn main() {
 
 fn basic_sess(sysroot: PathBuf) -> Session {
     let mut opts = basic_options();
-    opts.output_types = vec![OutputTypeExe];
+    opts.output_types.insert(OutputType::Exe, None);
     opts.maybe_sysroot = Some(sysroot);
 
     let descriptions = Registry::new(&rustc::DIAGNOSTICS);
index ea6971853fe998aa42fc23e3d7421f300a71ef9f..042048ec25f63c05096693257dff6b2d8f6a3a2d 100644 (file)
@@ -1,7 +1,5 @@
 -include ../tools.mk
 
-all:
-       $(CC) -std=c99 test.c -c -o $(TMPDIR)/test.o
-       $(AR) rcs $(TMPDIR)/libtest.a $(TMPDIR)/test.o
-       $(RUSTC) test.rs -L $(TMPDIR)
+all: $(call NATIVE_STATICLIB,test)
+       $(RUSTC) test.rs
        $(call RUN,test) || exit 1
index 1e66e3a53804f81c67727d051fac03b0838b766a..0d94c99a3948a9553c98cdd08195e224a26d7b0a 100644 (file)
@@ -2,4 +2,4 @@
 
 all:
                $(RUSTC) -o "" blank.rs 2>&1 | \
-                       grep 'No such file or directory'
+                       grep -i 'No such file or directory'
diff --git a/src/test/run-make/issue-28595/Makefile b/src/test/run-make/issue-28595/Makefile
new file mode 100644 (file)
index 0000000..61e9d0c
--- /dev/null
@@ -0,0 +1,6 @@
+-include ../tools.mk
+
+all: $(call NATIVE_STATICLIB,a) $(call NATIVE_STATICLIB,b)
+       $(RUSTC) a.rs
+       $(RUSTC) b.rs
+       $(call RUN,b)
diff --git a/src/test/run-make/issue-28595/a.c b/src/test/run-make/issue-28595/a.c
new file mode 100644 (file)
index 0000000..feacd7b
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+void a(void) {}
diff --git a/src/test/run-make/issue-28595/a.rs b/src/test/run-make/issue-28595/a.rs
new file mode 100644 (file)
index 0000000..7377a9f
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "rlib"]
+
+#[link(name = "a", kind = "static")]
+extern {
+    pub fn a();
+}
diff --git a/src/test/run-make/issue-28595/b.c b/src/test/run-make/issue-28595/b.c
new file mode 100644 (file)
index 0000000..de81fbc
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern void a(void);
+
+void b(void) {
+    a();
+}
+
diff --git a/src/test/run-make/issue-28595/b.rs b/src/test/run-make/issue-28595/b.rs
new file mode 100644 (file)
index 0000000..37ff346
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+extern crate a;
+
+#[link(name = "b", kind = "static")]
+extern {
+    pub fn b();
+}
+
+
+fn main() {
+    unsafe { b(); }
+}
index 116c7ae991cf67ae778218719addc8542f7c838f..eeea0e3714e7f18444b0ffd738b522ca5e7b42c7 100644 (file)
@@ -6,10 +6,12 @@
 CORRECT_DIR=$(TMPDIR)/correct
 WRONG_DIR=$(TMPDIR)/wrong
 
-all: $(TMPDIR)/libcorrect.a $(TMPDIR)/libwrong.a
+F := $(call NATIVE_STATICLIB_FILE,foo)
+
+all: $(call NATIVE_STATICLIB,correct) $(call NATIVE_STATICLIB,wrong)
        mkdir -p $(CORRECT_DIR) $(WRONG_DIR)
-       mv $(TMPDIR)/libcorrect.a $(CORRECT_DIR)/libfoo.a
-       mv $(TMPDIR)/libwrong.a $(WRONG_DIR)/libfoo.a
+       mv $(call NATIVE_STATICLIB,correct) $(CORRECT_DIR)/$(F)
+       mv $(call NATIVE_STATICLIB,wrong) $(WRONG_DIR)/$(F)
        $(RUSTC) main.rs -o $(TMPDIR)/should_succeed -L $(CORRECT_DIR) -L $(WRONG_DIR)
        $(call RUN,should_succeed)
        $(RUSTC) main.rs -o $(TMPDIR)/should_fail -L $(WRONG_DIR) -L $(CORRECT_DIR)
index 1871a5bbdc7f6dd0befd848c07e5a19b071bacbd..4befbe1446542ed99f22c695d4fc2aa001c8931d 100644 (file)
@@ -1,7 +1,5 @@
 -include ../tools.mk
 
-all:
-       $(CC) foo.c -c -o $(TMPDIR)/foo.o
-       $(AR) rcs $(TMPDIR)/libfoo.a $(TMPDIR)/foo.o
-       $(RUSTC) bar.rs -lfoo -L $(TMPDIR)
+all: $(call NATIVE_STATICLIB,foo)
+       $(RUSTC) bar.rs
        $(call RUN,bar) || exit 1
index 6125421bdeb6c91bbba5fe91863dde5b95f451ff..274401c448bada6adabad33b0c7acc3553973c75 100644 (file)
@@ -14,6 +14,7 @@
 #[linkage = "external"]
 static BAZ: i32 = 21;
 
+#[link(name = "foo", kind = "static")]
 extern {
     fn what() -> i32;
 }
diff --git a/src/test/run-make/linker-output-non-utf8/Makefile b/src/test/run-make/linker-output-non-utf8/Makefile
new file mode 100644 (file)
index 0000000..98fe83f
--- /dev/null
@@ -0,0 +1,24 @@
+-include ../tools.mk
+
+# Make sure we don't ICE if the linker prints a non-UTF-8 error message.
+
+ifdef IS_WINDOWS
+# ignore windows
+
+# This does not work in its current form on windows, possibly due to
+# gcc bugs or something about valid Windows paths.  See issue #29151
+# for more information.
+all:
+
+else
+
+# The zzz it to allow humans to tab complete or glob this thing.
+bad_dir := $(TMPDIR)/zzz$$'\xff'
+
+all:
+       $(RUSTC) library.rs
+       mkdir $(bad_dir)
+       mv $(TMPDIR)/liblibrary.a $(bad_dir)
+       LIBRARY_PATH=$(bad_dir) $(RUSTC) exec.rs 2>&1 | grep this_symbol_not_defined
+
+endif
diff --git a/src/test/run-make/linker-output-non-utf8/exec.rs b/src/test/run-make/linker-output-non-utf8/exec.rs
new file mode 100644 (file)
index 0000000..1c03eb4
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[link(name="library")]
+extern "C" {
+    fn foo();
+}
+
+fn main() { unsafe { foo(); } }
diff --git a/src/test/run-make/linker-output-non-utf8/library.rs b/src/test/run-make/linker-output-non-utf8/library.rs
new file mode 100644 (file)
index 0000000..194be26
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "staticlib"]
+
+extern "C" {
+    fn this_symbol_not_defined();
+}
+
+#[no_mangle]
+pub extern "C" fn foo() {
+    unsafe { this_symbol_not_defined(); }
+}
index 6165afbeb222f56ddf1c9d9f79fd429a324a441c..72c161abe9113f10665f6ea3449b843b4adecf55 100644 (file)
@@ -5,5 +5,7 @@ CC := $(CC:-g=)
 
 all:
        $(RUSTC) foo.rs -C lto
-       $(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) $(EXTRACFLAGS) $(EXTRACXXFLAGS)
+       $(CC) bar.c $(TMPDIR)/libfoo.a \
+               $(call OUT_EXE,bar) \
+               $(EXTRACFLAGS) $(EXTRACXXFLAGS)
        $(call RUN,bar)
index fdb6048dc4d527e0a639446b4ba4e2092fa55883..3f6a28c251a2fad4e3cd7a72bba83d89b94d54cb 100644 (file)
@@ -1,7 +1,12 @@
 -include ../tools.mk
 
+ifdef IS_MSVC
+# FIXME(#27979)
+all:
+else
 all:
        $(RUSTC) foo.rs
        $(RUSTC) bar.rs
        $(RUSTC) main.rs
        $(call RUN,main)
+endif
diff --git a/src/test/run-make/no-duplicate-libs/bar.c b/src/test/run-make/no-duplicate-libs/bar.c
deleted file mode 100644 (file)
index a7b02a2..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-// ignore-license
-extern void foo();
-
-void bar() { foo(); }
diff --git a/src/test/run-make/no-duplicate-libs/foo.c b/src/test/run-make/no-duplicate-libs/foo.c
deleted file mode 100644 (file)
index 2895ad4..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-// ignore-license
-void foo() {}
index 4efbd9ee48df21f3bae75e5710b3b29b82bf8167..b4b2e827e947eb32e65754fe88f16a99496d024f 100644 (file)
@@ -4,12 +4,14 @@ all:
        $(RUSTC) foo.rs --crate-type=rlib,dylib,staticlib
        $(call REMOVE_RLIBS,bar)
        $(call REMOVE_DYLIBS,bar)
-       rm $(TMPDIR)/$(call STATICLIB_GLOB,bar)
+       rm $(TMPDIR)/libbar.a
+       rm -f $(TMPDIR)/bar.{exp,lib,pdb}
        # Check that $(TMPDIR) is empty.
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
        $(RUSTC) foo.rs --crate-type=bin
        rm $(TMPDIR)/$(call BIN,bar)
+       rm -f $(TMPDIR)/bar.pdb
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
        $(RUSTC) foo.rs --emit=asm,llvm-ir,llvm-bc,obj,link
@@ -18,49 +20,91 @@ all:
        rm $(TMPDIR)/bar.s
        rm $(TMPDIR)/bar.o
        rm $(TMPDIR)/$(call BIN,bar)
+       rm -f $(TMPDIR)/bar.pdb
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
-       $(RUSTC) foo.rs --emit=asm -o $(TMPDIR)/foo
+       $(RUSTC) foo.rs --emit asm -o $(TMPDIR)/foo
+       rm $(TMPDIR)/foo
+       $(RUSTC) foo.rs --emit asm=$(TMPDIR)/foo
        rm $(TMPDIR)/foo
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
-       $(RUSTC) foo.rs --emit=llvm-bc -o $(TMPDIR)/foo
+       $(RUSTC) foo.rs --emit llvm-bc -o $(TMPDIR)/foo
+       rm $(TMPDIR)/foo
+       $(RUSTC) foo.rs --emit llvm-bc=$(TMPDIR)/foo
        rm $(TMPDIR)/foo
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
-       $(RUSTC) foo.rs --emit=llvm-ir -o $(TMPDIR)/foo
+       $(RUSTC) foo.rs --emit llvm-ir -o $(TMPDIR)/foo
+       rm $(TMPDIR)/foo
+       $(RUSTC) foo.rs --emit llvm-ir=$(TMPDIR)/foo
        rm $(TMPDIR)/foo
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
-       $(RUSTC) foo.rs --emit=obj -o $(TMPDIR)/foo
+       $(RUSTC) foo.rs --emit obj -o $(TMPDIR)/foo
+       rm $(TMPDIR)/foo
+       $(RUSTC) foo.rs --emit obj=$(TMPDIR)/foo
        rm $(TMPDIR)/foo
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
-       $(RUSTC) foo.rs --emit=link -o $(TMPDIR)/foo
+       $(RUSTC) foo.rs --emit link -o $(TMPDIR)/$(call BIN,foo)
        rm $(TMPDIR)/$(call BIN,foo)
+       $(RUSTC) foo.rs --emit link=$(TMPDIR)/$(call BIN,foo)
+       rm $(TMPDIR)/$(call BIN,foo)
+       rm -f $(TMPDIR)/foo.pdb
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
        $(RUSTC) foo.rs --crate-type=rlib -o $(TMPDIR)/foo
        rm $(TMPDIR)/foo
+       $(RUSTC) foo.rs --crate-type=rlib --emit link=$(TMPDIR)/foo
+       rm $(TMPDIR)/foo
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
-       $(RUSTC) foo.rs --crate-type=dylib -o $(TMPDIR)/foo
-       rm $(TMPDIR)/$(call BIN,foo)  # FIXME 13794
+       $(RUSTC) foo.rs --crate-type=dylib -o $(TMPDIR)/$(call BIN,foo)
+       rm $(TMPDIR)/$(call BIN,foo)
+       $(RUSTC) foo.rs --crate-type=dylib --emit link=$(TMPDIR)/$(call BIN,foo)
+       rm $(TMPDIR)/$(call BIN,foo)
+       rm -f $(TMPDIR)/foo.{exp,lib,pdb}
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
        $(RUSTC) foo.rs --crate-type=staticlib -o $(TMPDIR)/foo
        rm $(TMPDIR)/foo
+       $(RUSTC) foo.rs --crate-type=staticlib --emit link=$(TMPDIR)/foo
+       rm $(TMPDIR)/foo
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
-       $(RUSTC) foo.rs --crate-type=bin -o $(TMPDIR)/foo
+       $(RUSTC) foo.rs --crate-type=bin -o $(TMPDIR)/$(call BIN,foo)
        rm $(TMPDIR)/$(call BIN,foo)
+       $(RUSTC) foo.rs --crate-type=bin --emit link=$(TMPDIR)/$(call BIN,foo)
+       rm $(TMPDIR)/$(call BIN,foo)
+       rm -f $(TMPDIR)/foo.pdb
+       [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
+
+       $(RUSTC) foo.rs --emit llvm-ir=$(TMPDIR)/ir \
+                       --emit link \
+                       --crate-type=rlib
+       rm $(TMPDIR)/ir
+       rm $(TMPDIR)/libbar.rlib
+       [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
+
+       $(RUSTC) foo.rs --emit asm=$(TMPDIR)/asm \
+                       --emit llvm-ir=$(TMPDIR)/ir \
+                       --emit llvm-bc=$(TMPDIR)/bc \
+                       --emit obj=$(TMPDIR)/obj \
+                       --emit link=$(TMPDIR)/link \
+                       --crate-type=staticlib
+       rm $(TMPDIR)/asm
+       rm $(TMPDIR)/ir
+       rm $(TMPDIR)/bc
+       rm $(TMPDIR)/obj
+       rm $(TMPDIR)/link
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
        $(RUSTC) foo.rs --emit=asm,llvm-ir,llvm-bc,obj,link --crate-type=staticlib
        rm $(TMPDIR)/bar.ll
        rm $(TMPDIR)/bar.s
        rm $(TMPDIR)/bar.o
-       rm $(TMPDIR)/$(call STATICLIB_GLOB,bar)
+       rm $(TMPDIR)/libbar.a
        mv $(TMPDIR)/bar.bc $(TMPDIR)/foo.bc
        # Don't check that the $(TMPDIR) is empty - we left `foo.bc` for later
        # comparison.
index 2fcdd32bfcbd4c54b12d57367017a00f92e57496..b22f34fa35b54af8b262159d26d461e6dc301db6 100644 (file)
@@ -1,15 +1,21 @@
 -include ../tools.mk
 
-all:
+all: others
        $(RUSTC) -C relocation-model=dynamic-no-pic foo.rs
        $(call RUN,foo)
 
        $(RUSTC) -C relocation-model=default foo.rs
        $(call RUN,foo)
 
+       $(RUSTC) -C relocation-model=default --crate-type=dylib foo.rs
+       $(RUSTC) -C relocation-model=dynamic-no-pic --crate-type=dylib foo.rs
+
+ifdef IS_MSVC
+# FIXME(#28026)
+others:
+else
+others:
        $(RUSTC) -C relocation-model=static foo.rs
        $(call RUN,foo)
-
-       $(RUSTC) -C relocation-model=default --crate-type=dylib foo.rs
        $(RUSTC) -C relocation-model=static --crate-type=dylib foo.rs
-       $(RUSTC) -C relocation-model=dynamic-no-pic --crate-type=dylib foo.rs
+endif
index 701bdee1109ed323fc9f9e69fb8dbb5cf466a33d..7296fb9cc59368be1f1c00d6f9c5aca3f70cc7d9 100644 (file)
@@ -1,6 +1,6 @@
 -include ../tools.mk
 all: code
 krate2: krate2.rs
-       $(RUSTC) $< 
+       $(RUSTC) $<
 code: foo.rs krate2
        $(RUSTC) foo.rs -Zsave-analysis
index 4981ea475d3a8a595709b2902f7df19e0da1a8d8..3e4ba5af80c4de604c7c11528d0abaa4bd1b6093 100644 (file)
@@ -339,8 +339,27 @@ fn main() { // foo
     if let SomeEnum::Strings(..) = s7 {
         println!("hello!");
     }
+
+    for i in 0..5 {
+        foo_foo(i);
+    }
+
+    if let Some(x) = None {
+        foo_foo(x);
+    }
+
+    if false {
+    } else if let Some(y) = None {
+        foo_foo(y);
+    }
+
+    while let Some(z) = None {
+        foo_foo(z);
+    }
 }
 
+fn foo_foo(_: i32) {}
+
 impl Iterator for nofields {
     type Item = (usize, usize);
 
index 1505e679af01142b51d7c05f5deb3bd2d2bdcdc4..8bd05dc201fcfa1bf0b97ad3aef3aac29d029536 100644 (file)
@@ -1,9 +1,16 @@
 -include ../tools.mk
 
+TO_LINK := $(call DYLIB,bar)
+ifdef IS_MSVC
+LINK_ARG = $(TO_LINK:dll=lib)
+else
+LINK_ARG = $(TO_LINK)
+endif
+
 all:
        $(RUSTC) foo.rs
        $(RUSTC) bar.rs
-       $(CC) main.c -o $(call RUN_BINFILE,main) -lbar $(EXTRACFLAGS)
+       $(CC) main.c $(call OUT_EXE,main) $(LINK_ARG) $(EXTRACFLAGS)
        rm $(TMPDIR)/*.rlib
        rm $(call DYLIB,foo)
        $(call RUN,main)
index 223296286bd89aeb81b7717938766074bdce784f..23af568697f9fa083dd2aff87b4a0a38f618eb6a 100644 (file)
@@ -7,7 +7,7 @@ TARGET_RPATH_ENV = \
 
 BARE_RUSTC := $(HOST_RPATH_ENV) $(RUSTC)
 RUSTC := $(BARE_RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR)
-CC := $(CC) -L $(TMPDIR)
+#CC := $(CC) -L $(TMPDIR)
 HTMLDOCCK := $(PYTHON) $(S)/src/etc/htmldocck.py
 
 # This is the name of the binary we will generate and run; use this
@@ -19,8 +19,6 @@ RUN_BINFILE = $(TMPDIR)/$(1)
 # variable before running the binary.
 
 RLIB_GLOB = lib$(1)*.rlib
-STATICLIB = $(TMPDIR)/lib$(1).a
-STATICLIB_GLOB = lib$(1)*.a
 BIN = $(1)
 
 UNAME = $(shell uname)
@@ -33,27 +31,48 @@ RUN = $(TARGET_RPATH_ENV) $(RUN_BINFILE)
 FAIL = $(TARGET_RPATH_ENV) $(RUN_BINFILE) && exit 1 || exit 0
 DYLIB_GLOB = lib$(1)*.dylib
 DYLIB = $(TMPDIR)/lib$(1).dylib
-RPATH_LINK_SEARCH =
+STATICLIB = $(TMPDIR)/lib$(1).a
+STATICLIB_GLOB = lib$(1)*.a
 else
 ifdef IS_WINDOWS
 RUN = PATH="$(PATH):$(TARGET_RPATH_DIR)" $(RUN_BINFILE)
 FAIL = PATH="$(PATH):$(TARGET_RPATH_DIR)" $(RUN_BINFILE) && exit 1 || exit 0
 DYLIB_GLOB = $(1)*.dll
 DYLIB = $(TMPDIR)/$(1).dll
+STATICLIB = $(TMPDIR)/$(1).lib
+STATICLIB_GLOB = $(1)*.lib
 BIN = $(1).exe
-RPATH_LINK_SEARCH =
 else
 RUN = $(TARGET_RPATH_ENV) $(RUN_BINFILE)
 FAIL = $(TARGET_RPATH_ENV) $(RUN_BINFILE) && exit 1 || exit 0
 DYLIB_GLOB = lib$(1)*.so
 DYLIB = $(TMPDIR)/lib$(1).so
-RPATH_LINK_SEARCH = -Wl,-rpath-link=$(1)
+STATICLIB = $(TMPDIR)/lib$(1).a
+STATICLIB_GLOB = lib$(1)*.a
+endif
 endif
+
+ifdef IS_MSVC
+COMPILE_OBJ = $(CC) -c -Fo:`cygpath -w $(1)` $(2)
+NATIVE_STATICLIB_FILE = $(1).lib
+NATIVE_STATICLIB = $(TMPDIR)/$(call NATIVE_STATICLIB_FILE,$(1))
+OUT_EXE=-Fe:`cygpath -w $(TMPDIR)/$(call BIN,$(1))` \
+       -Fo:`cygpath -w $(TMPDIR)/$(1).obj`
+else
+COMPILE_OBJ = $(CC) -c -o $(1) $(2)
+NATIVE_STATICLIB_FILE = lib$(1).a
+NATIVE_STATICLIB = $(call STATICLIB,$(1))
+OUT_EXE=-o $(TMPDIR)/$(1)
 endif
 
+
 # Extra flags needed to compile a working executable with the standard library
 ifdef IS_WINDOWS
+ifdef IS_MSVC
+       EXTRACFLAGS := ws2_32.lib userenv.lib shell32.lib advapi32.lib
+else
        EXTRACFLAGS := -lws2_32 -luserenv
+endif
 else
 ifeq ($(UNAME),Darwin)
 else
@@ -66,6 +85,11 @@ ifeq ($(UNAME),Bitrig)
 else
 ifeq ($(UNAME),OpenBSD)
        EXTRACFLAGS := -lm -lpthread
+       # extend search lib for found estdc++ if build using gcc from
+       # ports under OpenBSD. This is needed for:
+       #  - run-make/execution-engine
+       #  - run-make/issue-19371
+       RUSTC := $(RUSTC) -L/usr/local/lib
 else
        EXTRACFLAGS := -lm -lrt -ldl -lpthread
        EXTRACXXFLAGS := -lstdc++
@@ -80,12 +104,20 @@ REMOVE_RLIBS      = rm $(TMPDIR)/$(call RLIB_GLOB,$(1))
 
 %.a: %.o
        ar crus $@ $<
+%.lib: lib%.o
+       ar crus $@ $<
 %.dylib: %.o
        $(CC) -dynamiclib -Wl,-dylib -o $@ $<
 %.so: %.o
        $(CC) -o $@ $< -shared
+
+ifdef IS_MSVC
+%.dll: lib%.o
+       $(CC) $< -link -dll -out:`cygpath -w $@`
+else
 %.dll: lib%.o
        $(CC) -o $@ $< -shared
+endif
 
 $(TMPDIR)/lib%.o: %.c
-       $(CC) -c -o $@ $<
+       $(call COMPILE_OBJ,$@,$<)
index 2bec41f3ee040d7dfb8cb33d912d8292b30dc881..f107e1042816f4e635a9f863a7a730cf6492fdf1 100644 (file)
 
 // ignore-cross-compile
 
-#![feature(rustc_private, path_ext)]
+#![feature(rustc_private)]
 
 extern crate rustc_back;
 
 use std::ffi::CString;
-use std::fs::{self, File, PathExt};
+use std::fs::{self, File};
 use rustc_back::tempdir::TempDir;
 
 fn rename_directory() {
index 80434f36b42d53e552c41b9b3b883a9a069af5f6..400458b614b39c22a47f15bc3620ab24b6bd2b22 100644 (file)
@@ -10,7 +10,7 @@
 
 use std::cell::Cell;
 
-#[derive(Show)]
+#[derive(Debug)]
 struct B<'a> {
     a: [Cell<Option<&'a B<'a>>>; 2]
 }
diff --git a/src/test/run-pass/augmented-assignments.rs b/src/test/run-pass/augmented-assignments.rs
new file mode 100644 (file)
index 0000000..eb4c1db
--- /dev/null
@@ -0,0 +1,164 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(augmented_assignments)]
+#![feature(op_assign_traits)]
+
+use std::mem;
+use std::ops::{
+    AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, DivAssign, Index, MulAssign, RemAssign,
+    ShlAssign, ShrAssign, SubAssign,
+};
+
+#[derive(Debug, PartialEq)]
+struct Int(i32);
+
+struct Slice([i32]);
+
+impl Slice {
+    fn new(slice: &mut [i32]) -> &mut Slice {
+        unsafe {
+            mem::transmute(slice)
+        }
+    }
+}
+
+fn main() {
+    let mut x = Int(1);
+
+    x += Int(2);
+    assert_eq!(x, Int(0b11));
+
+    x &= Int(0b01);
+    assert_eq!(x, Int(0b01));
+
+    x |= Int(0b10);
+    assert_eq!(x, Int(0b11));
+
+    x ^= Int(0b01);
+    assert_eq!(x, Int(0b10));
+
+    x /= Int(2);
+    assert_eq!(x, Int(1));
+
+    x *= Int(3);
+    assert_eq!(x, Int(3));
+
+    x %= Int(2);
+    assert_eq!(x, Int(1));
+
+    // overloaded RHS
+    x <<= 1u8;
+    assert_eq!(x, Int(2));
+
+    x <<= 1u16;
+    assert_eq!(x, Int(4));
+
+    x >>= 1u8;
+    assert_eq!(x, Int(2));
+
+    x >>= 1u16;
+    assert_eq!(x, Int(1));
+
+    x -= Int(1);
+    assert_eq!(x, Int(0));
+
+    // indexed LHS
+    let mut v = vec![Int(1), Int(2)];
+    v[0] += Int(2);
+    assert_eq!(v[0], Int(3));
+
+    // unsized RHS
+    let mut array = [0, 1, 2];
+    *Slice::new(&mut array) += 1;
+    assert_eq!(array[0], 1);
+    assert_eq!(array[1], 2);
+    assert_eq!(array[2], 3);
+}
+
+impl AddAssign for Int {
+    fn add_assign(&mut self, rhs: Int) {
+        self.0 += rhs.0;
+    }
+}
+
+impl BitAndAssign for Int {
+    fn bitand_assign(&mut self, rhs: Int) {
+        self.0 &= rhs.0;
+    }
+}
+
+impl BitOrAssign for Int {
+    fn bitor_assign(&mut self, rhs: Int) {
+        self.0 |= rhs.0;
+    }
+}
+
+impl BitXorAssign for Int {
+    fn bitxor_assign(&mut self, rhs: Int) {
+        self.0 ^= rhs.0;
+    }
+}
+
+impl DivAssign for Int {
+    fn div_assign(&mut self, rhs: Int) {
+        self.0 /= rhs.0;
+    }
+}
+
+impl MulAssign for Int {
+    fn mul_assign(&mut self, rhs: Int) {
+        self.0 *= rhs.0;
+    }
+}
+
+impl RemAssign for Int {
+    fn rem_assign(&mut self, rhs: Int) {
+        self.0 %= rhs.0;
+    }
+}
+
+impl ShlAssign<u8> for Int {
+    fn shl_assign(&mut self, rhs: u8) {
+        self.0 <<= rhs;
+    }
+}
+
+impl ShlAssign<u16> for Int {
+    fn shl_assign(&mut self, rhs: u16) {
+        self.0 <<= rhs;
+    }
+}
+
+impl ShrAssign<u8> for Int {
+    fn shr_assign(&mut self, rhs: u8) {
+        self.0 >>= rhs;
+    }
+}
+
+impl ShrAssign<u16> for Int {
+    fn shr_assign(&mut self, rhs: u16) {
+        self.0 >>= rhs;
+    }
+}
+
+impl SubAssign for Int {
+    fn sub_assign(&mut self, rhs: Int) {
+        self.0 -= rhs.0;
+    }
+}
+
+impl AddAssign<i32> for Slice {
+    fn add_assign(&mut self, rhs: i32) {
+        for lhs in &mut self.0 {
+            *lhs += rhs;
+        }
+    }
+}
index 40acb6eb9fe81cfd4e444b75b28eec930dc1a105..5c5364de6a86b59d63c66aee92ed80057ea9834d 100644 (file)
@@ -21,6 +21,6 @@ impl double for usize {
 }
 
 pub fn main() {
-    let x: Box<_> = box() (box 3usize as Box<double>);
+    let x: Box<_> = box (box 3usize as Box<double>);
     assert_eq!(x.double(), 6);
 }
index 045e8d952adaa0ffdd383e48327a19b94a5acf92..93cb0cb0af23aa501b6d0a2c96ad797d5b121dc9 100644 (file)
@@ -39,5 +39,5 @@ pub fn main() {
     assert_eq!(v, 22);
 
     let v = Counter::new(22).inc().inc().get();
-    assert_eq!(v, 24);;
+    assert_eq!(v, 24);
 }
diff --git a/src/test/run-pass/cfg-target-vendor.rs b/src/test/run-pass/cfg-target-vendor.rs
new file mode 100644 (file)
index 0000000..787ae52
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(cfg_target_vendor)]
+
+#[cfg(target_vendor = "unknown")]
+pub fn main() {
+}
+
+#[cfg(not(target_vendor = "unknown"))]
+pub fn main() {
+}
index 5377d9a62b91a48be06ee049fcb8e89f74244de9..46cd708a13969fda910c89cf5f8d9020465896e1 100644 (file)
@@ -10,7 +10,7 @@
 
 use std::mem;
 
-#[derive(PartialEq, Show)]
+#[derive(PartialEq, Debug)]
 enum Foo {
     A(u32),
     Bar([u16; 4]),
diff --git a/src/test/run-pass/const-fn-const-eval.rs b/src/test/run-pass/const-fn-const-eval.rs
new file mode 100644 (file)
index 0000000..77c70fe
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(const_fn)]
+
+const fn add(x: usize, y: usize) -> usize {
+    x + y
+}
+
+const ARR: [i32; add(1, 2)] = [5, 6, 7];
+
+pub fn main() {}
diff --git a/src/test/run-pass/const-unsafe-fn.rs b/src/test/run-pass/const-unsafe-fn.rs
new file mode 100644 (file)
index 0000000..2511cfd
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// A quick test of 'unsafe const fn' functionality
+
+#![feature(const_fn)]
+
+const unsafe fn dummy(v: u32) -> u32 {
+    !v
+}
+
+struct Type;
+impl Type {
+    const unsafe fn new() -> Type {
+        Type
+    }
+}
+
+const VAL: u32 = unsafe { dummy(0xFFFF) };
+const TYPE_INST: Type = unsafe { Type::new() };
+
+fn main() {
+    assert_eq!(VAL, 0xFFFF0000);
+}
index 83ce0db365f8bb8afb5d212ae5c032b732954099..d6b6d673ca5433f223b03430debd5f5cf885a2e9 100644 (file)
@@ -30,26 +30,25 @@ macro_rules! t {
     ($e:expr) => (match $e { Ok(e) => e, Err(e) => panic!("error: {}", e) })
 }
 
+#[test]
 fn test_destroy_once() {
     let mut p = sleeper();
-    match p.kill() {
-        Ok(()) => {}
-        Err(e) => panic!("error: {}", e),
-    }
+    t!(p.kill());
 }
 
 #[cfg(unix)]
 pub fn sleeper() -> Child {
-    Command::new("sleep").arg("1000").spawn().unwrap()
+    t!(Command::new("sleep").arg("1000").spawn())
 }
 #[cfg(windows)]
 pub fn sleeper() -> Child {
     // There's a `timeout` command on windows, but it doesn't like having
     // its output piped, so instead just ping ourselves a few times with
     // gaps in between so we're sure this process is alive for awhile
-    Command::new("ping").arg("127.0.0.1").arg("-n").arg("1000").spawn().unwrap()
+    t!(Command::new("ping").arg("127.0.0.1").arg("-n").arg("1000").spawn())
 }
 
+#[test]
 fn test_destroy_twice() {
     let mut p = sleeper();
     t!(p.kill()); // this shouldn't crash...
@@ -58,21 +57,20 @@ fn test_destroy_twice() {
 
 #[test]
 fn test_destroy_actually_kills() {
-    #[cfg(all(unix,not(target_os="android")))]
-    static BLOCK_COMMAND: &'static str = "cat";
-
-    #[cfg(all(unix,target_os="android"))]
-    static BLOCK_COMMAND: &'static str = "/system/bin/cat";
-
-    #[cfg(windows)]
-    static BLOCK_COMMAND: &'static str = "cmd";
+    let cmd = if cfg!(windows) {
+        "cmd"
+    } else if cfg!(target_os = "android") {
+        "/system/bin/cat"
+    } else {
+        "cat"
+    };
 
     // this process will stay alive indefinitely trying to read from stdin
-    let mut p = Command::new(BLOCK_COMMAND)
-                        .stdin(Stdio::piped())
-                        .spawn().unwrap();
+    let mut p = t!(Command::new(cmd)
+                           .stdin(Stdio::piped())
+                           .spawn());
 
-    p.kill().unwrap();
+    t!(p.kill());
 
     // Don't let this test time out, this should be quick
     let (tx, rx) = channel();
@@ -82,7 +80,7 @@ fn test_destroy_actually_kills() {
             process::exit(1);
         }
     });
-    let code = p.wait().unwrap().code();
+    let code = t!(p.wait()).code();
     if cfg!(windows) {
         assert!(code.is_some());
     } else {
index 43507f0cb00bd475f22978c4401168c169b6ab25..028b3f43e2ae8ba44fea79ca1db254a471283600 100644 (file)
@@ -24,7 +24,7 @@ extern crate crate_method_reexport_grrrrrrr2;
 pub fn main() {
     use crate_method_reexport_grrrrrrr2::rust::add;
     use crate_method_reexport_grrrrrrr2::rust::cx;
-    let x: Box<_> = box () ();
+    let x: Box<_> = box ();
     x.cx();
     let y = ();
     y.add("hi".to_string());
index 494d62c773770111c642970110dd8d92d0f27632..69a7f888bbe09d49422cdc0e7a5a6fc723593d63 100644 (file)
@@ -8,8 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[derive(Show)]
-//~^ WARNING derive(Show) is deprecated
+#![feature(rustc_private)]
+
+extern crate serialize;
+
+#[derive(Encodable)]
+//~^ WARNING derive(Encodable) is deprecated in favor of derive(RustcEncodable)
 struct Test1;
 
 fn main() { }
index 2770260a10e1c44ebb18e661edf122c6bc34afc5..a31df0fd93e16a1aaca8508d97feec1bf52ae3bb 100644 (file)
 // through the collection, for every collection type that supports
 // this.
 
-#![feature(vecmap)]
+// HIGH LEVEL DESCRIPTION OF THE TEST ARCHITECTURE
+// -----------------------------------------------
+//
+// We pick a data structure and want to make a cyclic construction
+// from it. Each test of interest is labelled starting with "Cycle N:
+// { ... }" where N is the test number and the "..."`is filled in with
+// a graphviz-style description of the graph structure that the
+// author believes is being made. So "{ a -> b, b -> (c,d), (c,d) -> e }"
+// describes a line connected to a diamond:
+//
+//                           c
+//                          / \
+//                     a - b   e
+//                          \ /
+//                           d
+//
+// (Note that the above directed graph is actually acyclic.)
+//
+// The different graph structures are often composed of different data
+// types. Some may be built atop `Vec`, others atop `HashMap`, etc.
+//
+// For each graph structure, we actually *confirm* that a cycle exists
+// (as a safe-guard against a test author accidentally leaving it out)
+// by traversing each graph and "proving" that a cycle exists within it.
+//
+// To do this, while trying to keep the code uniform (despite working
+// with different underlying collection and smart-pointer types), we
+// have a standard traversal API:
+//
+// 1. every node in the graph carries a `mark` (a u32, init'ed to 0).
+//
+// 2. every node provides a method to visit its children
+//
+// 3. a traversal attmepts to visit the nodes of the graph and prove that
+//    it sees the same node twice. It does this by setting the mark of each
+//    node to a fresh non-zero value, and if it sees the current mark, it
+//    "knows" that it must have found a cycle, and stops attempting further
+//    traversal.
+//
+// 4. each traversal is controlled by a bit-string that tells it which child
+//    it visit when it can take different paths. As a simple example,
+//    in a binary tree, 0 could mean "left" (and 1, "right"), so that
+//    "00010" means "left, left, left, right, left". (In general it will
+//    read as many bits as it needs to choose one child.)
+//
+//    The graphs in this test are all meant to be very small, and thus
+//    short bitstrings of less than 64 bits should always suffice.
+//
+//    (An earlier version of this test infrastructure simply had any
+//    given traversal visit all children it encountered, in a
+//    depth-first manner; one problem with this approach is that an
+//    acyclic graph can still have sharing, which would then be treated
+//    as a repeat mark and reported as a detected cycle.)
+//
+// The travseral code is a little more complicated because it has been
+// programmed in a somewhat defensive manner. For example it also has
+// a max threshold for the number of nodes it will visit, to guard
+// against scenarios where the nodes are not correctly setting their
+// mark when asked. There are various other methods not discussed here
+// that are for aiding debugging the test when it runs, such as the
+// `name` method that all nodes provide.
+//
+// So each test:
+//
+// 1. allocates the nodes in the graph,
+//
+// 2. sets up the links in the graph,
+//
+// 3. clones the "ContextData"
+//
+// 4. chooses a new current mark value for this test
+//
+// 5. initiates a traversal, potentially from multiple starting points
+//    (aka "roots"), with a given control-string (potentially a
+//    different string for each root). if it does start from a
+//    distinct root, then such a test should also increment the
+//    current mark value, so that this traversal is considered
+//    distinct from the prior one on this graph structure.
+//
+//    Note that most of the tests work with the default control string
+//    of all-zeroes.
+//
+// 6. assert that the context confirms that it actually saw a cycle (since a traversal
+//    might have terminated, e.g. on a tree structure that contained no cycles).
 
-use std::cell::Cell;
+use std::cell::{Cell, RefCell};
 use std::cmp::Ordering;
 use std::collections::BinaryHeap;
 use std::collections::HashMap;
@@ -35,6 +118,8 @@ use std::collections::VecDeque;
 use std::collections::btree_map::BTreeMap;
 use std::collections::btree_set::BTreeSet;
 use std::hash::{Hash, Hasher};
+use std::rc::Rc;
+use std::sync::{Arc, RwLock, Mutex};
 
 const PRINT: bool = false;
 
@@ -47,8 +132,28 @@ pub fn main() {
         skipped: 0,
         curr_mark: 0,
         saw_prev_marked: false,
+        control_bits: 0,
     };
 
+    // SANITY CHECK FOR TEST SUITE (thus unnumbered)
+    // Not a cycle: { v[0] -> (v[1], v[2]), v[1] -> v[3], v[2] -> v[3] };
+    let v: Vec<S2> = vec![Named::new("s0"),
+                          Named::new("s1"),
+                          Named::new("s2"),
+                          Named::new("s3")];
+    v[0].next.set((Some(&v[1]), Some(&v[2])));
+    v[1].next.set((Some(&v[3]), None));
+    v[2].next.set((Some(&v[3]), None));
+    v[3].next.set((None, None));
+
+    let mut c = c_orig.clone();
+    c.curr_mark = 10;
+    assert!(!c.saw_prev_marked);
+    v[0].descend_into_self(&mut c);
+    assert!(!c.saw_prev_marked); // <-- different from below, b/c acyclic above
+
+    if PRINT { println!(""); }
+
     // Cycle 1: { v[0] -> v[1], v[1] -> v[0] };
     // does not exercise `v` itself
     let v: Vec<S> = vec![Named::new("s0"),
@@ -59,7 +164,7 @@ pub fn main() {
     let mut c = c_orig.clone();
     c.curr_mark = 10;
     assert!(!c.saw_prev_marked);
-    v[0].for_each_child(&mut c);
+    v[0].descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
     if PRINT { println!(""); }
@@ -72,7 +177,7 @@ pub fn main() {
     let mut c = c_orig.clone();
     c.curr_mark = 20;
     assert!(!c.saw_prev_marked);
-    v.for_each_child(&mut c);
+    v.descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
     if PRINT { println!(""); }
@@ -93,7 +198,7 @@ pub fn main() {
     for (key, _) in h.iter() {
         c.curr_mark += 1;
         c.saw_prev_marked = false;
-        key.for_each_child(&mut c);
+        key.descend_into_self(&mut c);
         assert!(c.saw_prev_marked);
     }
 
@@ -115,7 +220,7 @@ pub fn main() {
     for (key, _) in h.iter() {
         c.curr_mark += 1;
         c.saw_prev_marked = false;
-        key.for_each_child(&mut c);
+        key.descend_into_self(&mut c);
         assert!(c.saw_prev_marked);
         // break;
     }
@@ -133,7 +238,7 @@ pub fn main() {
     let mut c = c_orig.clone();
     c.curr_mark = 50;
     assert!(!c.saw_prev_marked);
-    vd[0].for_each_child(&mut c);
+    vd[0].descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
     if PRINT { println!(""); }
@@ -148,7 +253,7 @@ pub fn main() {
     let mut c = c_orig.clone();
     c.curr_mark = 60;
     assert!(!c.saw_prev_marked);
-    vd[0].for_each_child(&mut c);
+    vd[0].descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
     if PRINT { println!(""); }
@@ -163,7 +268,7 @@ pub fn main() {
     let mut c = c_orig.clone();
     c.curr_mark = 70;
     assert!(!c.saw_prev_marked);
-    vm[&0].for_each_child(&mut c);
+    vm[&0].descend_into_self(&mut c);
     assert!(c.saw_prev_marked);
 
     if PRINT { println!(""); }
@@ -181,7 +286,7 @@ pub fn main() {
     for e in &ll {
         c.curr_mark += 1;
         c.saw_prev_marked = false;
-        e.for_each_child(&mut c);
+        e.descend_into_self(&mut c);
         assert!(c.saw_prev_marked);
         // break;
     }
@@ -201,7 +306,7 @@ pub fn main() {
     for b in &bh {
         c.curr_mark += 1;
         c.saw_prev_marked = false;
-        b.for_each_child(&mut c);
+        b.descend_into_self(&mut c);
         assert!(c.saw_prev_marked);
         // break;
     }
@@ -222,7 +327,7 @@ pub fn main() {
     for (k, _) in &btm {
         c.curr_mark += 1;
         c.saw_prev_marked = false;
-        k.for_each_child(&mut c);
+        k.descend_into_self(&mut c);
         assert!(c.saw_prev_marked);
         // break;
     }
@@ -242,10 +347,98 @@ pub fn main() {
     for b in &bts {
         c.curr_mark += 1;
         c.saw_prev_marked = false;
-        b.for_each_child(&mut c);
+        b.descend_into_self(&mut c);
         assert!(c.saw_prev_marked);
         // break;
     }
+
+    if PRINT { println!(""); }
+
+    // Cycle 11: { rc0 -> (rc1, rc2), rc1 -> (), rc2 -> rc0 }
+    let (rc0, rc1, rc2): (RCRC, RCRC, RCRC);
+    rc0 = RCRC::new("rcrc0");
+    rc1 = RCRC::new("rcrc1");
+    rc2 = RCRC::new("rcrc2");
+    rc0.0.borrow_mut().children.0 = Some(&rc1);
+    rc0.0.borrow_mut().children.1 = Some(&rc2);
+    rc2.0.borrow_mut().children.0 = Some(&rc0);
+
+    let mut c = c_orig.clone();
+    c.control_bits = 0b1;
+    c.curr_mark = 110;
+    assert!(!c.saw_prev_marked);
+    rc0.descend_into_self(&mut c);
+    assert!(c.saw_prev_marked);
+
+    if PRINT { println!(""); }
+
+    // We want to take the previous Rc case and generalize it to Arc.
+    //
+    // We can use refcells if we're single-threaded (as this test is).
+    // If one were to generalize these constructions to a
+    // multi-threaded context, then it might seem like we could choose
+    // between either a RwLock or a Mutex to hold the owned arcs on
+    // each node.
+    //
+    // Part of the point of this test is to actually confirm that the
+    // cycle exists by traversing it. We can do that just fine with an
+    // RwLock (since we can grab the child pointers in read-only
+    // mode), but we cannot lock a std::sync::Mutex to guard reading
+    // from each node via the same pattern, since once you hit the
+    // cycle, you'll be trying to acquring the same lock twice.
+    // (We deal with this by exiting the traversal early if try_lock fails.)
+
+    // Cycle 12: { arc0 -> (arc1, arc2), arc1 -> (), arc2 -> arc0 }, refcells
+    let (arc0, arc1, arc2): (ARCRC, ARCRC, ARCRC);
+    arc0 = ARCRC::new("arcrc0");
+    arc1 = ARCRC::new("arcrc1");
+    arc2 = ARCRC::new("arcrc2");
+    arc0.0.borrow_mut().children.0 = Some(&arc1);
+    arc0.0.borrow_mut().children.1 = Some(&arc2);
+    arc2.0.borrow_mut().children.0 = Some(&arc0);
+
+    let mut c = c_orig.clone();
+    c.control_bits = 0b1;
+    c.curr_mark = 110;
+    assert!(!c.saw_prev_marked);
+    arc0.descend_into_self(&mut c);
+    assert!(c.saw_prev_marked);
+
+    if PRINT { println!(""); }
+
+    // Cycle 13: { arc0 -> (arc1, arc2), arc1 -> (), arc2 -> arc0 }, rwlocks
+    let (arc0, arc1, arc2): (ARCRW, ARCRW, ARCRW);
+    arc0 = ARCRW::new("arcrw0");
+    arc1 = ARCRW::new("arcrw1");
+    arc2 = ARCRW::new("arcrw2");
+    arc0.0.write().unwrap().children.0 = Some(&arc1);
+    arc0.0.write().unwrap().children.1 = Some(&arc2);
+    arc2.0.write().unwrap().children.0 = Some(&arc0);
+
+    let mut c = c_orig.clone();
+    c.control_bits = 0b1;
+    c.curr_mark = 110;
+    assert!(!c.saw_prev_marked);
+    arc0.descend_into_self(&mut c);
+    assert!(c.saw_prev_marked);
+
+    if PRINT { println!(""); }
+
+    // Cycle 14: { arc0 -> (arc1, arc2), arc1 -> (), arc2 -> arc0 }, mutexs
+    let (arc0, arc1, arc2): (ARCM, ARCM, ARCM);
+    arc0 = ARCM::new("arcm0");
+    arc1 = ARCM::new("arcm1");
+    arc2 = ARCM::new("arcm2");
+    arc0.1.lock().unwrap().children.0 = Some(&arc1);
+    arc0.1.lock().unwrap().children.1 = Some(&arc2);
+    arc2.1.lock().unwrap().children.0 = Some(&arc0);
+
+    let mut c = c_orig.clone();
+    c.control_bits = 0b1;
+    c.curr_mark = 110;
+    assert!(!c.saw_prev_marked);
+    arc0.descend_into_self(&mut c);
+    assert!(c.saw_prev_marked);
 }
 
 trait Named {
@@ -276,6 +469,26 @@ impl<'a> Marked<u32> for S<'a> {
     fn set_mark(&self, mark: u32) { self.mark.set(mark); }
 }
 
+struct S2<'a> {
+    name: &'static str,
+    mark: Cell<u32>,
+    next: Cell<(Option<&'a S2<'a>>, Option<&'a S2<'a>>)>,
+}
+
+impl<'a> Named for S2<'a> {
+    fn new<'b>(name: &'static str) -> S2<'b> {
+        S2 { name: name, mark: Cell::new(0), next: Cell::new((None, None)) }
+    }
+    fn name(&self) -> &str { self.name }
+}
+
+impl<'a> Marked<u32> for S2<'a> {
+    fn mark(&self) -> u32 { self.mark.get() }
+    fn set_mark(&self, mark: u32) {
+        self.mark.set(mark);
+    }
+}
+
 struct V<'a> {
     name: &'static str,
     mark: Cell<u32>,
@@ -549,8 +762,168 @@ impl<'a> Ord for BTS<'a> {
     }
 }
 
+#[derive(Clone)]
+struct RCRCData<'a> {
+    name: &'static str,
+    mark: Cell<u32>,
+    children: (Option<&'a RCRC<'a>>, Option<&'a RCRC<'a>>),
+}
+#[derive(Clone)]
+struct RCRC<'a>(Rc<RefCell<RCRCData<'a>>>);
+
+impl<'a> Named for RCRC<'a> {
+    fn new(name: &'static str) -> Self {
+        RCRC(Rc::new(RefCell::new(RCRCData {
+            name: name, mark: Cell::new(0), children: (None, None), })))
+    }
+    fn name(&self) -> &str { self.0.borrow().name }
+}
+
+impl<'a> Marked<u32> for RCRC<'a> {
+    fn mark(&self) -> u32 { self.0.borrow().mark.get() }
+    fn set_mark(&self, mark: u32) { self.0.borrow().mark.set(mark); }
+}
+
+impl<'a> Children<'a> for RCRC<'a> {
+    fn count_children(&self) -> usize { 2 }
+    fn descend_one_child<C>(&self, context: &mut C, index: usize)
+        where C: Context + PrePost<Self>, Self: Sized
+    {
+        let children = &self.0.borrow().children;
+        let child = match index {
+            0 => if let Some(child) = children.0 { child } else { return; },
+            1 => if let Some(child) = children.1 { child } else { return; },
+            _ => panic!("bad children"),
+        };
+        // println!("S2 {} descending into child {} at index {}", self.name, child.name, index);
+        child.descend_into_self(context);
+    }
+}
+#[derive(Clone)]
+struct ARCRCData<'a> {
+    name: &'static str,
+    mark: Cell<u32>,
+    children: (Option<&'a ARCRC<'a>>, Option<&'a ARCRC<'a>>),
+}
+#[derive(Clone)]
+struct ARCRC<'a>(Arc<RefCell<ARCRCData<'a>>>);
+
+impl<'a> Named for ARCRC<'a> {
+    fn new(name: &'static str) -> Self {
+        ARCRC(Arc::new(RefCell::new(ARCRCData {
+            name: name, mark: Cell::new(0), children: (None, None), })))
+    }
+    fn name(&self) -> &str { self.0.borrow().name }
+}
+
+impl<'a> Marked<u32> for ARCRC<'a> {
+    fn mark(&self) -> u32 { self.0.borrow().mark.get() }
+    fn set_mark(&self, mark: u32) { self.0.borrow().mark.set(mark); }
+}
+
+impl<'a> Children<'a> for ARCRC<'a> {
+    fn count_children(&self) -> usize { 2 }
+    fn descend_one_child<C>(&self, context: &mut C, index: usize)
+        where C: Context + PrePost<Self>, Self: Sized
+    {
+        let children = &self.0.borrow().children;
+        match index {
+            0 => if let Some(ref child) = children.0 {
+                child.descend_into_self(context);
+            },
+            1 => if let Some(ref child) = children.1 {
+                child.descend_into_self(context);
+            },
+            _ => panic!("bad children!"),
+        }
+    }
+}
+
+#[derive(Clone)]
+struct ARCMData<'a> {
+    mark: Cell<u32>,
+    children: (Option<&'a ARCM<'a>>, Option<&'a ARCM<'a>>),
+}
+
+#[derive(Clone)]
+struct ARCM<'a>(&'static str, Arc<Mutex<ARCMData<'a>>>);
+
+impl<'a> Named for ARCM<'a> {
+    fn new(name: &'static str) -> Self {
+        ARCM(name, Arc::new(Mutex::new(ARCMData {
+            mark: Cell::new(0), children: (None, None), })))
+    }
+    fn name(&self) -> &str { self.0 }
+}
+
+impl<'a> Marked<u32> for ARCM<'a> {
+    fn mark(&self) -> u32 { self.1.lock().unwrap().mark.get() }
+    fn set_mark(&self, mark: u32) { self.1.lock().unwrap().mark.set(mark); }
+}
+
+impl<'a> Children<'a> for ARCM<'a> {
+    fn count_children(&self) -> usize { 2 }
+    fn descend_one_child<C>(&self, context: &mut C, index: usize)
+        where C: Context + PrePost<Self>, Self: Sized
+    {
+        let ref children = if let Ok(data) = self.1.try_lock() {
+            data.children
+        } else { return; };
+        match index {
+            0 => if let Some(ref child) = children.0 {
+                child.descend_into_self(context);
+            },
+            1 => if let Some(ref child) = children.1 {
+                child.descend_into_self(context);
+            },
+            _ => panic!("bad children!"),
+        }
+    }
+}
+
+#[derive(Clone)]
+struct ARCRWData<'a> {
+    name: &'static str,
+    mark: Cell<u32>,
+    children: (Option<&'a ARCRW<'a>>, Option<&'a ARCRW<'a>>),
+}
+
+#[derive(Clone)]
+struct ARCRW<'a>(Arc<RwLock<ARCRWData<'a>>>);
+
+impl<'a> Named for ARCRW<'a> {
+    fn new(name: &'static str) -> Self {
+        ARCRW(Arc::new(RwLock::new(ARCRWData {
+            name: name, mark: Cell::new(0), children: (None, None), })))
+    }
+    fn name(&self) -> &str { self.0.read().unwrap().name }
+}
+
+impl<'a> Marked<u32> for ARCRW<'a> {
+    fn mark(&self) -> u32 { self.0.read().unwrap().mark.get() }
+    fn set_mark(&self, mark: u32) { self.0.read().unwrap().mark.set(mark); }
+}
+
+impl<'a> Children<'a> for ARCRW<'a> {
+    fn count_children(&self) -> usize { 2 }
+    fn descend_one_child<C>(&self, context: &mut C, index: usize)
+        where C: Context + PrePost<Self>, Self: Sized
+    {
+        let children = &self.0.read().unwrap().children;
+        match index {
+            0 => if let Some(ref child) = children.0 {
+                child.descend_into_self(context);
+            },
+            1 => if let Some(ref child) = children.1 {
+                child.descend_into_self(context);
+            },
+            _ => panic!("bad children!"),
+        }
+    }
+}
 
 trait Context {
+    fn next_index(&mut self, len: usize) -> usize;
     fn should_act(&self) -> bool;
     fn increase_visited(&mut self);
     fn increase_skipped(&mut self);
@@ -565,9 +938,17 @@ trait PrePost<T> {
 }
 
 trait Children<'a> {
-    fn for_each_child<C>(&self, context: &mut C)
+    fn count_children(&self) -> usize;
+    fn descend_one_child<C>(&self, context: &mut C, index: usize)
         where C: Context + PrePost<Self>, Self: Sized;
 
+    fn next_child<C>(&self, context: &mut C)
+        where C: Context + PrePost<Self>, Self: Sized
+    {
+        let index = context.next_index(self.count_children());
+        self.descend_one_child(context, index);
+    }
+
     fn descend_into_self<C>(&self, context: &mut C)
         where C: Context + PrePost<Self>, Self: Sized
     {
@@ -575,7 +956,7 @@ trait Children<'a> {
         if context.should_act() {
             context.increase_visited();
             context.increase_depth();
-            self.for_each_child(context);
+            self.next_child(context);
             context.decrease_depth();
         } else {
             context.hit_limit(self);
@@ -594,51 +975,73 @@ trait Children<'a> {
 }
 
 impl<'a> Children<'a> for S<'a> {
-    fn for_each_child<C>(&self, context: &mut C)
-        where C: Context + PrePost<S<'a>>
+    fn count_children(&self) -> usize { 1 }
+    fn descend_one_child<C>(&self, context: &mut C, _: usize)
+        where C: Context + PrePost<Self>, Self: Sized {
+            self.descend(&self.next, context);
+        }
+}
+
+impl<'a> Children<'a> for S2<'a> {
+    fn count_children(&self) -> usize { 2 }
+    fn descend_one_child<C>(&self, context: &mut C, index: usize)
+        where C: Context + PrePost<Self>, Self: Sized
     {
-        self.descend(&self.next, context);
+        let children = self.next.get();
+        let child = match index {
+            0 => if let Some(child) = children.0 { child } else { return; },
+            1 => if let Some(child) = children.1 { child } else { return; },
+            _ => panic!("bad children"),
+        };
+        // println!("S2 {} descending into child {} at index {}", self.name, child.name, index);
+        child.descend_into_self(context);
     }
 }
 
 impl<'a> Children<'a> for V<'a> {
-    fn for_each_child<C>(&self, context: &mut C)
-        where C: Context + PrePost<V<'a>>
+    fn count_children(&self) -> usize { self.contents.len() }
+    fn descend_one_child<C>(&self, context: &mut C, index: usize)
+        where C: Context + PrePost<Self>, Self: Sized
     {
-        for r in &self.contents {
-            self.descend(r, context);
+        if let Some(child) = self.contents[index].get() {
+            child.descend_into_self(context);
         }
     }
 }
 
 impl<'a> Children<'a> for H<'a> {
-    fn for_each_child<C>(&self, context: &mut C)
-        where C: Context + PrePost<H<'a>>
+    fn count_children(&self) -> usize { 1 }
+    fn descend_one_child<C>(&self, context: &mut C, _: usize)
+        where C: Context + PrePost<Self>, Self: Sized
     {
         self.descend(&self.next, context);
     }
 }
 
 impl<'a> Children<'a> for HM<'a> {
-    fn for_each_child<C>(&self, context: &mut C)
-        where C: Context + PrePost<HM<'a>>
+    fn count_children(&self) -> usize {
+        if let Some(m) = self.contents.get() { 2 * m.iter().count() } else { 0 }
+    }
+    fn descend_one_child<C>(&self, context: &mut C, index: usize)
+        where C: Context + PrePost<Self>, Self: Sized
     {
         if let Some(ref hm) = self.contents.get() {
-            for (k, v) in hm.iter() {
-                for r in &[k, v] {
-                    r.descend_into_self(context);
-                }
+            for (k, v) in hm.iter().nth(index / 2) {
+                [k, v][index % 2].descend_into_self(context);
             }
         }
     }
 }
 
 impl<'a> Children<'a> for VD<'a> {
-    fn for_each_child<C>(&self, context: &mut C)
-        where C: Context + PrePost<VD<'a>>
+    fn count_children(&self) -> usize {
+        if let Some(d) = self.contents.get() { d.iter().count() } else { 0 }
+    }
+    fn descend_one_child<C>(&self, context: &mut C, index: usize)
+        where C: Context + PrePost<Self>, Self: Sized
     {
         if let Some(ref vd) = self.contents.get() {
-            for r in vd.iter() {
+            for r in vd.iter().nth(index) {
                 r.descend_into_self(context);
             }
         }
@@ -646,11 +1049,14 @@ impl<'a> Children<'a> for VD<'a> {
 }
 
 impl<'a> Children<'a> for VM<'a> {
-    fn for_each_child<C>(&self, context: &mut C)
+    fn count_children(&self) -> usize {
+        if let Some(m) = self.contents.get() { m.iter().count() } else { 0 }
+    }
+    fn descend_one_child<C>(&self, context: &mut C, index: usize)
         where C: Context + PrePost<VM<'a>>
     {
         if let Some(ref vd) = self.contents.get() {
-            for (_idx, r) in vd.iter() {
+            for (_idx, r) in vd.iter().nth(index) {
                 r.descend_into_self(context);
             }
         }
@@ -658,11 +1064,14 @@ impl<'a> Children<'a> for VM<'a> {
 }
 
 impl<'a> Children<'a> for LL<'a> {
-    fn for_each_child<C>(&self, context: &mut C)
+    fn count_children(&self) -> usize {
+        if let Some(l) = self.contents.get() { l.iter().count() } else { 0 }
+    }
+    fn descend_one_child<C>(&self, context: &mut C, index: usize)
         where C: Context + PrePost<LL<'a>>
     {
         if let Some(ref ll) = self.contents.get() {
-            for r in ll.iter() {
+            for r in ll.iter().nth(index) {
                 r.descend_into_self(context);
             }
         }
@@ -670,11 +1079,14 @@ impl<'a> Children<'a> for LL<'a> {
 }
 
 impl<'a> Children<'a> for BH<'a> {
-    fn for_each_child<C>(&self, context: &mut C)
+    fn count_children(&self) -> usize {
+        if let Some(h) = self.contents.get() { h.iter().count() } else { 0 }
+    }
+    fn descend_one_child<C>(&self, context: &mut C, index: usize)
         where C: Context + PrePost<BH<'a>>
     {
         if let Some(ref bh) = self.contents.get() {
-            for r in bh.iter() {
+            for r in bh.iter().nth(index) {
                 r.descend_into_self(context);
             }
         }
@@ -682,25 +1094,29 @@ impl<'a> Children<'a> for BH<'a> {
 }
 
 impl<'a> Children<'a> for BTM<'a> {
-    fn for_each_child<C>(&self, context: &mut C)
+    fn count_children(&self) -> usize {
+        if let Some(m) = self.contents.get() { 2 * m.iter().count() } else { 0 }
+    }
+    fn descend_one_child<C>(&self, context: &mut C, index: usize)
         where C: Context + PrePost<BTM<'a>>
     {
         if let Some(ref bh) = self.contents.get() {
-            for (k, v) in bh.iter() {
-                for r in &[k, v] {
-                    r.descend_into_self(context);
-                }
+            for (k, v) in bh.iter().nth(index / 2) {
+                [k, v][index % 2].descend_into_self(context);
             }
         }
     }
 }
 
 impl<'a> Children<'a> for BTS<'a> {
-    fn for_each_child<C>(&self, context: &mut C)
+    fn count_children(&self) -> usize {
+        if let Some(s) = self.contents.get() { s.iter().count() } else { 0 }
+    }
+    fn descend_one_child<C>(&self, context: &mut C, index: usize)
         where C: Context + PrePost<BTS<'a>>
     {
         if let Some(ref bh) = self.contents.get() {
-            for r in bh.iter() {
+            for r in bh.iter().nth(index) {
                 r.descend_into_self(context);
             }
         }
@@ -716,9 +1132,27 @@ struct ContextData {
     skipped: usize,
     curr_mark: u32,
     saw_prev_marked: bool,
+    control_bits: u64,
 }
 
 impl Context for ContextData {
+    fn next_index(&mut self, len: usize) -> usize {
+        if len < 2 { return 0; }
+        let mut pow2 = len.next_power_of_two();
+        let _pow2_orig = pow2;
+        let mut idx = 0;
+        let mut bits = self.control_bits;
+        while pow2 > 1 {
+            idx = (idx << 1) | (bits & 1) as usize;
+            bits = bits >> 1;
+            pow2 = pow2 >> 1;
+        }
+        idx = idx % len;
+        // println!("next_index({} [{:b}]) says {}, pre(bits): {:b} post(bits): {:b}",
+        //          len, _pow2_orig, idx, self.control_bits, bits);
+        self.control_bits = bits;
+        return idx;
+    }
     fn should_act(&self) -> bool {
         self.curr_depth < self.max_depth && self.visited < self.max_visits
     }
index b0c4f4ca272a03e52f3656a4c51b8395aca34714..db30bfbf747901499fea6b30f1c9260a5f184dfc 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Check that a arena (TypedArena) can carry elements whose drop
+// Check that an arena (TypedArena) can carry elements whose drop
 // methods might access borrowed data, as long as the borrowed data
 // has lifetime that strictly outlives the arena itself.
 //
diff --git a/src/test/run-pass/empty-struct-braces.rs b/src/test/run-pass/empty-struct-braces.rs
new file mode 100644 (file)
index 0000000..f2fbf2d
--- /dev/null
@@ -0,0 +1,88 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Empty struct defined with braces add names into type namespace
+// Empty struct defined without braces add names into both type and value namespaces
+
+#![feature(braced_empty_structs)]
+
+struct Empty1 {}
+struct Empty2;
+struct Empty3 {}
+const Empty3: Empty3 = Empty3 {};
+
+enum E {
+    Empty4 {},
+    Empty5,
+}
+
+fn main() {
+    let e1: Empty1 = Empty1 {};
+    let e2: Empty2 = Empty2 {};
+    let e2: Empty2 = Empty2;
+    let e3: Empty3 = Empty3 {};
+    let e3: Empty3 = Empty3;
+    let e4: E = E::Empty4 {};
+    // let e5: E = E::Empty5 {}; // Issue #28692
+    let e5: E = E::Empty5;
+
+    match e1 {
+        Empty1 {} => {}
+    }
+    match e2 {
+        Empty2 {} => {}
+    }
+    match e3 {
+        Empty3 {} => {}
+    }
+    match e4 {
+        E::Empty4 {} => {}
+        _ => {}
+    }
+    // Issue #28692
+    // match e5 {
+    //     E::Empty5 {} => {}
+    //     _ => {}
+    // }
+
+    match e1 {
+        Empty1 { .. } => {}
+    }
+    match e2 {
+        Empty2 { .. } => {}
+    }
+    match e3 {
+        Empty3 { .. } => {}
+    }
+    match e4 {
+        E::Empty4 { .. } => {}
+        _ => {}
+    }
+    // Issue #28692
+    // match e5 {
+    //     E::Empty5 { .. } => {}
+    //     _ => {}
+    // }
+
+    match e2 {
+        Empty2 => {}
+    }
+    match e3 {
+        Empty3 => {}
+    }
+    match e5 {
+        E::Empty5 => {}
+        _ => {}
+    }
+
+    let e11: Empty1 = Empty1 { ..e1 };
+    let e22: Empty2 = Empty2 { ..e2 };
+    let e33: Empty3 = Empty3 { ..e3 };
+}
diff --git a/src/test/run-pass/feature-gate-negate-unsigned.rs b/src/test/run-pass/feature-gate-negate-unsigned.rs
deleted file mode 100644 (file)
index 95c8e62..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that negating unsigned integers is gated by `negate_unsigned` feature
-// gate
-
-struct S;
-impl std::ops::Neg for S {
-    type Output = u32;
-    fn neg(self) -> u32 { 0 }
-}
-
-const _MAX: usize = -1;
-//~^ WARN unary negation of unsigned integers will be feature gated in the future
-
-fn main() {
-    let a = -1;
-    //~^ WARN unary negation of unsigned integers will be feature gated in the future
-    let _b : u8 = a; // for infering variable a to u8.
-
-    -a;
-    //~^ WARN unary negation of unsigned integers will be feature gated in the future
-
-    let _d = -1u8;
-    //~^ WARN unary negation of unsigned integers will be feature gated in the future
-
-    for _ in -10..10u8 {}
-    //~^ WARN unary negation of unsigned integers will be feature gated in the future
-
-    -S; // should not trigger the gate; issue 26840
-}
index c8adb6ccc0ab8598379bbf2388d27c04d206871c..2cc033b8a46e136cbe6f00130ab6f15f6bc359dd 100644 (file)
@@ -74,6 +74,10 @@ pub fn main() {
     t!(format!("{:?}", 10_usize), "10");
     t!(format!("{:?}", "true"), "\"true\"");
     t!(format!("{:?}", "foo\nbar"), "\"foo\\nbar\"");
+    t!(format!("{:?}", "foo\n\"bar\"\r\n\'baz\'\t\\qux\\"),
+       r#""foo\n\"bar\"\r\n\'baz\'\t\\qux\\""#);
+    t!(format!("{:?}", "foo\0bar\x01baz\u{3b1}q\u{75}x"),
+       r#""foo\u{0}bar\u{1}baz\u{3b1}qux""#);
     t!(format!("{:o}", 10_usize), "12");
     t!(format!("{:x}", 10_usize), "a");
     t!(format!("{:X}", 10_usize), "A");
index 0d43f1ca70669b848295031abc23d2fae0c689c3..209b4acb09586935210a62d5e72272720e45eaf9 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Ensure that an user-defined type admits multiple inherent methods
+// Ensure that a user-defined type admits multiple inherent methods
 // with the same name, which can be called on values that have a
 // precise enough type to allow distinguishing between the methods.
 
index 9d680d1962f8f7a515e0a4146eef4aea0c256360..b5ef6020b57d0fdcfa6755f1014df5c34b197e6a 100644 (file)
@@ -16,5 +16,5 @@
 pub fn main() {
     fn f() {
     };
-    let _: Box<fn()> = box() (f as fn());
+    let _: Box<fn()> = box (f as fn());
 }
diff --git a/src/test/run-pass/issue-11047.rs b/src/test/run-pass/issue-11047.rs
new file mode 100644 (file)
index 0000000..1d97d57
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that static methods can be invoked on `type` aliases
+
+#![allow(unused_variables)]
+
+pub mod foo {
+    pub mod bar {
+        pub mod baz {
+            pub struct Qux;
+
+            impl Qux {
+                pub fn new() {}
+            }
+        }
+    }
+}
+
+fn main() {
+
+    type Ham = foo::bar::baz::Qux;
+    let foo = foo::bar::baz::Qux::new();  // invoke directly
+    let bar = Ham::new();                 // invoke via type alias
+
+    type StringVec = Vec<String>;
+    let sv = StringVec::new();
+}
index 81588e8ef78dbd207cdf32a1b04ffd36140c1fd5..c1997fac74b7854db0ac7cef149b08fb66399c6f 100644 (file)
@@ -1,4 +1,3 @@
-
  // 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.
diff --git a/src/test/run-pass/issue-14564.rs b/src/test/run-pass/issue-14564.rs
deleted file mode 100644 (file)
index a661437..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-mod Foo { }
-struct Foo;
-impl Foo { }
-
-fn main() { }
index 371e926ab18d5f05062de87439c779215453e732..d3c9fe9161ccb52259606a86f63755e0e73f4c59 100644 (file)
@@ -59,5 +59,5 @@ fn match_indices<'a, M, T: IntoMatcher<'a, M>>(s: &'a str, from: T) -> MatchIndi
 fn main() {
     let s = "abcbdef";
     match_indices(s, |c: char| c == 'b')
-        .collect::<Vec<(usize, usize)>>();
+        .collect::<Vec<_>>();
 }
diff --git a/src/test/run-pass/issue-16819.rs b/src/test/run-pass/issue-16819.rs
new file mode 100644 (file)
index 0000000..a9abb99
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//`#[cfg]` on struct field permits empty unusable struct
+
+#![feature(braced_empty_structs)]
+
+struct S {
+    #[cfg(untrue)]
+    a: int,
+}
+
+fn main() {
+    let s = S {};
+}
diff --git a/src/test/run-pass/issue-17336.rs b/src/test/run-pass/issue-17336.rs
new file mode 100644 (file)
index 0000000..ce04237
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[allow(dead_code)]
+fn check(a: &str) {
+    let x = a as *const str;
+    x == x;
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-21410.rs b/src/test/run-pass/issue-21410.rs
new file mode 100644 (file)
index 0000000..bc525ba
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn g<F>(_: F) where F: FnOnce(Option<F>) {}
+
+fn main() {
+    g(|_| {  });
+}
diff --git a/src/test/run-pass/issue-21922.rs b/src/test/run-pass/issue-21922.rs
new file mode 100644 (file)
index 0000000..2f538b3
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::ops::Add;
+fn show(z: i32) {
+    println!("{}", z)
+}
+fn main() {
+    let x = 23;
+    let y = 42;
+    show(Add::add( x,  y));
+    show(Add::add( x, &y));
+    show(Add::add(&x,  y));
+    show(Add::add(&x, &y));
+    show( x +  y);
+    show( x + &y);
+    show(&x +  y);
+    show(&x + &y);
+}
diff --git a/src/test/run-pass/issue-22403.rs b/src/test/run-pass/issue-22403.rs
new file mode 100644 (file)
index 0000000..7bd66e5
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let x = Box::new([1, 2, 3]);
+    let y = x as Box<[i32]>;
+    println!("y: {:?}", y);
+}
diff --git a/src/test/run-pass/issue-22781.rs b/src/test/run-pass/issue-22781.rs
new file mode 100644 (file)
index 0000000..1aa32f2
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::collections::HashMap;
+use std::collections::hash_map::Entry::Vacant;
+
+pub fn foo() {
+    type F = Box<Fn(&()) + 'static>;
+    let mut map: HashMap<(), F> = HashMap::new();
+    let x: &mut F = match map.entry(()) {
+        Vacant(_) => unimplemented!(),
+        _ => unimplemented!()
+    };
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-22814.rs b/src/test/run-pass/issue-22814.rs
new file mode 100644 (file)
index 0000000..6afcd77
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Test {}
+
+macro_rules! test {
+( $($name:ident)+) => (
+    impl<$($name: Test),*> Test for ($($name,)*) {
+    }
+)
+}
+
+test!(A B C);
+
+fn main() {}
diff --git a/src/test/run-pass/issue-23036.rs b/src/test/run-pass/issue-23036.rs
new file mode 100644 (file)
index 0000000..0ed4126
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::collections::HashMap;
+use std::path::Path;
+
+fn main() {
+    let mut map = HashMap::new();
+    map.insert(Path::new("a"), 0);
+    map.get(Path::new("a"));
+}
diff --git a/src/test/run-pass/issue-23891.rs b/src/test/run-pass/issue-23891.rs
new file mode 100644 (file)
index 0000000..55536de
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! id {
+    ($s: pat) => ($s);
+}
+
+fn main() {
+    match (Some(123), Some(456)) {
+        (id!(Some(a)), _) | (_, id!(Some(a))) => println!("{}", a),
+        _ => (),
+    }
+}
index 3617b0d3a577788fde8705b1926c775dd43ac632..fde32cb9023928286f806f1e7bd9d8a3071a9aa4 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Regression test for #24085. Errors were occuring in region
+// Regression test for #24085. Errors were occurring in region
 // inference due to the requirement that `'a:b'`, which was getting
 // incorrectly translated in connection with the closure below.
 
diff --git a/src/test/run-pass/issue-24389.rs b/src/test/run-pass/issue-24389.rs
new file mode 100644 (file)
index 0000000..41599fa
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(dead_code)]
+
+struct Foo;
+
+impl Foo {
+    fn new() -> Self { Foo }
+    fn bar() { Self::new(); }
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-24533.rs b/src/test/run-pass/issue-24533.rs
new file mode 100644 (file)
index 0000000..440a418
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::slice::Iter;
+use std::io::{Error, ErrorKind, Result};
+use std::vec::*;
+
+fn foo(it: &mut Iter<u8>) -> Result<u8> {
+    Ok(*it.next().unwrap())
+}
+
+fn bar() -> Result<u8> {
+    let data: Vec<u8> = Vec::new();
+
+    if true {
+        return Err(Error::new(ErrorKind::NotFound, "msg"));
+    }
+
+    let mut it = data.iter();
+    foo(&mut it)
+}
+
+fn main() {
+    bar();
+}
index 4512bcc2000bf56971654451e65708d932dc58d9..9fa482022982b719aa3494fccc85c9cfa6a24ad9 100644 (file)
@@ -13,6 +13,8 @@
 
 #![allow(non_camel_case_types)]
 
+#![feature(dropck_parametricity)]
+
 trait UserDefined { }
 
 impl UserDefined for i32 { }
@@ -26,7 +28,10 @@ impl<'a, T> UserDefined for &'a T { }
 macro_rules! impl_drop {
     ($Bound:ident, $Id:ident) => {
         struct $Id<T:$Bound>(T);
-        impl <T:$Bound> Drop for $Id<T> { fn drop(&mut self) { } }
+        impl <T:$Bound> Drop for $Id<T> {
+            #[unsafe_destructor_blind_to_params]
+            fn drop(&mut self) { }
+        }
     }
 }
 
diff --git a/src/test/run-pass/issue-24956.rs b/src/test/run-pass/issue-24956.rs
new file mode 100644 (file)
index 0000000..501b713
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo(bool);
+const NEW_FALSE: bool = false;
+const STATIC_FOO: Foo = Foo(NEW_FALSE);
+
+pub fn main() {
+    match (Foo(false)) {
+        STATIC_FOO => 3,
+        _ => 11
+    };
+}
diff --git a/src/test/run-pass/issue-24972.rs b/src/test/run-pass/issue-24972.rs
new file mode 100644 (file)
index 0000000..ae7eb84
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_private)]
+
+extern crate serialize;
+
+use serialize::{Encodable, Decodable};
+use std::fmt::Display;
+
+pub trait Entity : Decodable + Encodable + Sized {
+    type Key: Clone + Decodable + Encodable + ToString + Display + Eq + Ord + Sized;
+
+    fn id(&self) -> Self::Key;
+
+    fn find_by_id(id: Self::Key) -> Option<Self>;
+}
+
+pub struct DbRef<E: Entity> {
+    pub id: E::Key,
+}
+
+impl<E> DbRef<E> where E: Entity {
+    fn get(self) -> Option<E> {
+        E::find_by_id(self.id)
+    }
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-25439.rs b/src/test/run-pass/issue-25439.rs
new file mode 100644 (file)
index 0000000..88c48f4
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Helper<'a, F: 'a>(&'a F);
+
+fn fix<F>(f: F) -> i32 where F: Fn(Helper<F>, i32) -> i32 {
+    f(Helper(&f), 8)
+}
+
+fn main() {
+    fix(|_, x| x);
+}
diff --git a/src/test/run-pass/issue-25693.rs b/src/test/run-pass/issue-25693.rs
new file mode 100644 (file)
index 0000000..aee89be
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub trait Paramters { type SelfRef; }
+
+struct RP<'a> { _marker: std::marker::PhantomData<&'a ()> }
+struct BP;
+
+impl<'a> Paramters for RP<'a> { type SelfRef = &'a X<RP<'a>>; }
+impl Paramters for BP { type SelfRef = Box<X<BP>>; }
+
+pub struct Y;
+pub enum X<P: Paramters> {
+    Nothing,
+    SameAgain(P::SelfRef, Y)
+}
+
+fn main() {
+    let bnil: Box<X<BP>> = Box::new(X::Nothing);
+    let bx: Box<X<BP>> = Box::new(X::SameAgain(bnil, Y));
+    let rnil: X<RP> = X::Nothing;
+    let rx: X<RP> = X::SameAgain(&rnil, Y);
+}
diff --git a/src/test/run-pass/issue-26095.rs b/src/test/run-pass/issue-26095.rs
new file mode 100644 (file)
index 0000000..f34685c
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(associated_consts)]
+
+trait HasNumber<T> {
+    const Number: usize;
+}
+
+enum One {}
+enum Two {}
+
+enum Foo {}
+
+impl<T> HasNumber<T> for One {
+    const Number: usize = 1;
+}
+
+impl<T> HasNumber<T> for Two {
+    const Number: usize = 2;
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-26905.rs b/src/test/run-pass/issue-26905.rs
new file mode 100644 (file)
index 0000000..0ad193b
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(unsize, coerce_unsized)]
+
+// Verfies that PhantomData is ignored for DST coercions
+
+use std::marker::{Unsize, PhantomData};
+use std::ops::CoerceUnsized;
+
+struct MyRc<T: ?Sized> {
+    _ptr: *const T,
+    _boo: PhantomData<T>,
+}
+
+impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<MyRc<U>> for MyRc<T>{ }
+
+fn main() {
+    let data = [1, 2, 3];
+    let iter = data.iter();
+    let x = MyRc { _ptr: &iter, _boo: PhantomData };
+    let _y: MyRc<Iterator<Item=&u32>> = x;
+}
+
diff --git a/src/test/run-pass/issue-27105.rs b/src/test/run-pass/issue-27105.rs
new file mode 100644 (file)
index 0000000..3836ad0
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::cell::RefCell;
+use std::rc::Rc;
+
+pub struct Callbacks {
+    callbacks: Vec<Rc<RefCell<FnMut(i32)>>>,
+}
+
+impl Callbacks {
+    pub fn register<F: FnMut(i32)+'static>(&mut self, callback: F) {
+        self.callbacks.push(Rc::new(RefCell::new(callback)));
+    }
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-27320.rs b/src/test/run-pass/issue-27320.rs
new file mode 100644 (file)
index 0000000..dde1d3b
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! piece(
+    ($piece:pat) => ($piece);
+);
+
+enum Piece {A, B}
+
+fn main() {
+    match Piece::A {
+        piece!(pt@ Piece::A) | piece!(pt@ Piece::B) => {}
+    }
+}
diff --git a/src/test/run-pass/issue-28189.rs b/src/test/run-pass/issue-28189.rs
new file mode 100644 (file)
index 0000000..0e624a7
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct S<T>(T) where [T; (||{}, 1).1]: Copy;
+
+fn main() {
+
+}
diff --git a/src/test/run-pass/issue-28279.rs b/src/test/run-pass/issue-28279.rs
new file mode 100644 (file)
index 0000000..ae40ce4
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::rc::Rc;
+
+fn test1() -> Rc<for<'a> Fn(&'a usize) + 'static> {
+    if let Some(_) = Some(1) {
+        loop{}
+    } else {
+        loop{}
+    }
+}
+
+fn test2() -> *mut for<'a> Fn(&'a usize) + 'static {
+    if let Some(_) = Some(1) {
+        loop{}
+    } else {
+        loop{}
+    }
+}
+
+fn main() {}
+
diff --git a/src/test/run-pass/issue-28561.rs b/src/test/run-pass/issue-28561.rs
new file mode 100644 (file)
index 0000000..8c73830
--- /dev/null
@@ -0,0 +1,120 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[derive(Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
+struct Array<T> {
+    f00: [T; 00],
+    f01: [T; 01],
+    f02: [T; 02],
+    f03: [T; 03],
+    f04: [T; 04],
+    f05: [T; 05],
+    f06: [T; 06],
+    f07: [T; 07],
+    f08: [T; 08],
+    f09: [T; 09],
+    f10: [T; 10],
+    f11: [T; 11],
+    f12: [T; 12],
+    f13: [T; 13],
+    f14: [T; 14],
+    f15: [T; 15],
+    f16: [T; 16],
+    f17: [T; 17],
+    f18: [T; 18],
+    f19: [T; 19],
+    f20: [T; 20],
+    f21: [T; 21],
+    f22: [T; 22],
+    f23: [T; 23],
+    f24: [T; 24],
+    f25: [T; 25],
+    f26: [T; 26],
+    f27: [T; 27],
+    f28: [T; 28],
+    f29: [T; 29],
+    f30: [T; 30],
+    f31: [T; 31],
+    f32: [T; 32],
+}
+
+// FIXME(#7622): merge with `Array` once `[T; N]: Clone` where `T: Clone`
+#[derive(Clone, Copy)]
+struct CopyArray<T: Copy> {
+    f00: [T; 00],
+    f01: [T; 01],
+    f02: [T; 02],
+    f03: [T; 03],
+    f04: [T; 04],
+    f05: [T; 05],
+    f06: [T; 06],
+    f07: [T; 07],
+    f08: [T; 08],
+    f09: [T; 09],
+    f10: [T; 10],
+    f11: [T; 11],
+    f12: [T; 12],
+    f13: [T; 13],
+    f14: [T; 14],
+    f15: [T; 15],
+    f16: [T; 16],
+    f17: [T; 17],
+    f18: [T; 18],
+    f19: [T; 19],
+    f20: [T; 20],
+    f21: [T; 21],
+    f22: [T; 22],
+    f23: [T; 23],
+    f24: [T; 24],
+    f25: [T; 25],
+    f26: [T; 26],
+    f27: [T; 27],
+    f28: [T; 28],
+    f29: [T; 29],
+    f30: [T; 30],
+    f31: [T; 31],
+    f32: [T; 32],
+}
+
+#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
+struct Fn<A, B, C, D, E, F, G, H, I, J, K, L> {
+    f00: fn(),
+    f01: fn(A),
+    f02: fn(A, B),
+    f03: fn(A, B, C),
+    f04: fn(A, B, C, D),
+    f05: fn(A, B, C, D, E),
+    f06: fn(A, B, C, D, E, F),
+    f07: fn(A, B, C, D, E, F, G),
+    f08: fn(A, B, C, D, E, F, G, H),
+    f09: fn(A, B, C, D, E, F, G, H, I),
+    f10: fn(A, B, C, D, E, F, G, H, I, J),
+    f11: fn(A, B, C, D, E, F, G, H, I, J, K),
+    f12: fn(A, B, C, D, E, F, G, H, I, J, K, L),
+}
+
+#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
+struct Tuple<A, B, C, D, E, F, G, H, I, J, K, L> {
+    f00: (),
+    f01: (A),
+    f02: (A, B),
+    f03: (A, B, C),
+    f04: (A, B, C, D),
+    f05: (A, B, C, D, E),
+    f06: (A, B, C, D, E, F),
+    f07: (A, B, C, D, E, F, G),
+    f08: (A, B, C, D, E, F, G, H),
+    f09: (A, B, C, D, E, F, G, H, I),
+    f10: (A, B, C, D, E, F, G, H, I, J),
+    f11: (A, B, C, D, E, F, G, H, I, J, K),
+    f12: (A, B, C, D, E, F, G, H, I, J, K, L),
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-28676.rs b/src/test/run-pass/issue-28676.rs
new file mode 100644 (file)
index 0000000..b8d43c3
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+
+#[derive(Copy, Clone)]
+pub struct Quad { a: u64, b: u64, c: u64, d: u64 }
+
+mod rustrt {
+    use super::Quad;
+
+    #[link(name = "rust_test_helpers")]
+    extern {
+        pub fn get_c_many_params(_: *const (), _: *const (),
+                                 _: *const (), _: *const (), f: Quad) -> u64;
+    }
+}
+
+fn test() {
+    unsafe {
+        let null = std::ptr::null();
+        let q = Quad {
+            a: 1,
+            b: 2,
+            c: 3,
+            d: 4
+        };
+        assert_eq!(rustrt::get_c_many_params(null, null, null, null, q), q.c);
+    }
+}
+
+pub fn main() {
+    test();
+}
diff --git a/src/test/run-pass/issue-28822.rs b/src/test/run-pass/issue-28822.rs
new file mode 100644 (file)
index 0000000..5a010f2
--- /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(const_fn)]
+
+fn main() {}
+
+const fn size_ofs(_: usize) {}
+const fn size_ofs2(_foo: usize) {}
diff --git a/src/test/run-pass/issue-28839.rs b/src/test/run-pass/issue-28839.rs
new file mode 100644 (file)
index 0000000..a101229
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-pretty : (#23623) problems with newlines before // comments
+
+pub struct Foo;
+
+pub fn get_foo2<'a>(foo: &'a mut Option<&'a mut Foo>) -> &'a mut Foo {
+    match foo {
+        // Ensure that this is not considered a move, but rather a reborrow.
+        &mut Some(ref mut x) => *x,
+        &mut None => panic!(),
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/run-pass/issue-28936.rs b/src/test/run-pass/issue-28936.rs
new file mode 100644 (file)
index 0000000..2a932cd
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub type Session = i32;
+pub struct StreamParser<'a, T> {
+    _tokens: T,
+    _session: &'a mut Session,
+}
+
+impl<'a, T> StreamParser<'a, T> {
+    pub fn thing(&mut self) -> bool { true }
+}
+
+pub fn parse_stream<T: Iterator<Item=i32>, U, F>(
+        _session: &mut Session, _tokens: T, _f: F) -> U
+    where F: Fn(&mut StreamParser<T>) -> U { panic!(); }
+
+pub fn thing(session: &mut Session) {
+    let mut stream = vec!(1, 2, 3).into_iter();
+
+    let _b = parse_stream(session,
+                          stream.by_ref(),
+                          // replacing the above with the following fixes it
+                          //&mut stream,
+                          |p| p.thing());
+
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-28983.rs b/src/test/run-pass/issue-28983.rs
new file mode 100644 (file)
index 0000000..658e9e1
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Test { type T; }
+
+impl Test for u32 {
+    type T = i32;
+}
+
+pub mod export {
+    #[no_mangle]
+    pub extern "C" fn issue_28983(t: <u32 as ::Test>::T) -> i32 { t*3 }
+}
+
+// to test both exporting and importing functions, import
+// a function from ourselves.
+extern "C" {
+    fn issue_28983(t: <u32 as Test>::T) -> i32;
+}
+
+fn main() {
+    assert_eq!(export::issue_28983(2), 6);
+    assert_eq!(unsafe { issue_28983(3) }, 9);
+}
diff --git a/src/test/run-pass/issue-28999.rs b/src/test/run-pass/issue-28999.rs
new file mode 100644 (file)
index 0000000..87112ef
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub struct Xyz<'a, V> {
+    pub v: (V, &'a u32),
+}
+
+pub fn eq<'a, 's, 't, V>(this: &'s Xyz<'a, V>, other: &'t Xyz<'a, V>) -> bool
+        where V: PartialEq {
+    this.v == other.v
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-29037.rs b/src/test/run-pass/issue-29037.rs
new file mode 100644 (file)
index 0000000..dc1d67c
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This test ensures that each pointer type `P<X>` is covariant in `X`.
+
+use std::rc::Rc;
+use std::sync::Arc;
+
+fn a<'r>(x: Box<&'static str>) -> Box<&'r str> {
+    x
+}
+
+fn b<'r, 'w>(x: &'w &'static str) -> &'w &'r str {
+    x
+}
+
+fn c<'r>(x: Arc<&'static str>) -> Arc<&'r str> {
+    x
+}
+
+fn d<'r>(x: Rc<&'static str>) -> Rc<&'r str> {
+    x
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-29048.rs b/src/test/run-pass/issue-29048.rs
new file mode 100644 (file)
index 0000000..48f4327
--- /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.
+
+pub struct Chan;
+pub struct ChanSelect<'c, T> {
+    chans: Vec<(&'c Chan, T)>,
+}
+impl<'c, T> ChanSelect<'c, T> {
+    pub fn add_recv_ret(&mut self, chan: &'c Chan, ret: T)
+    {
+        self.chans.push((chan, ret));
+    }
+}
+fn main() {}
diff --git a/src/test/run-pass/issue-29166.rs b/src/test/run-pass/issue-29166.rs
new file mode 100644 (file)
index 0000000..193f977
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This test ensures that vec.into_iter does not overconstrain element lifetime.
+
+pub fn main() {
+    original_report();
+    revision_1();
+    revision_2();
+}
+
+fn original_report() {
+    drop(vec![&()].into_iter())
+}
+
+fn revision_1() {
+    // below is what above `vec!` expands into at time of this writing.
+    drop(<[_]>::into_vec(::std::boxed::Box::new([&()])).into_iter())
+}
+
+fn revision_2() {
+    drop((match (Vec::new(), &()) { (mut v, b) => { v.push(b); v } }).into_iter())
+}
index fd8e1e6b036baa8123567679e216a977b352af55..511344a792f46c43a05d3040bd7718a684153272 100644 (file)
@@ -28,7 +28,7 @@ pub fn main() {
   //   let y = box ({a: 4});
   //    let z = box ({a: 4} as it);
   //    let z = box ({a: true} as it);
-    let z: Box<_> = box () (box true as Box<it>);
+    let z: Box<_> = box (box true as Box<it>);
     //  x.f();
     // y.f();
     // (*z).f();
diff --git a/src/test/run-pass/issue-29746.rs b/src/test/run-pass/issue-29746.rs
new file mode 100644 (file)
index 0000000..61c601a
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// zip!(a1,a2,a3,a4) is equivalent to:
+//  a1.zip(a2).zip(a3).zip(a4).map(|(((x1,x2),x3),x4)| (x1,x2,x3,x4))
+macro_rules! zip {
+    // Entry point
+    ([$a:expr, $b:expr, $($rest:expr),*]) => {
+        zip!([$($rest),*], $a.zip($b), (x,y), [x,y])
+    };
+
+    // Intermediate steps to build the zipped expression, the match pattern, and
+    //  and the output tuple of the closure, using macro hygene to repeatedly
+    //  introduce new variables named 'x'.
+    ([$a:expr, $($rest:expr),*], $zip:expr, $pat:pat, [$($flat:expr),*]) => {
+        zip!([$($rest),*], $zip.zip($a), ($pat,x), [$($flat),*, x])
+    };
+
+    // Final step
+    ([], $zip:expr, $pat:pat, [$($flat:expr),+]) => {
+        $zip.map(|$pat| ($($flat),+))
+    };
+
+    // Comma
+    ([$a:expr], $zip:expr, $pat:pat, [$($flat:expr),*]) => {
+        zip!([$a,], $zip, $pat, [$($flat),*])
+    };
+}
+
+fn main() {
+    let p1 = vec![1i32,    2].into_iter();
+    let p2 = vec!["10",    "20"].into_iter();
+    let p3 = vec![100u16,  200].into_iter();
+    let p4 = vec![1000i64, 2000].into_iter();
+
+    let e = zip!([p1,p2,p3,p4]).collect::<Vec<_>>();
+    assert_eq!(e[0], (1i32,"10",100u16,1000i64));
+}
diff --git a/src/test/run-pass/issue-30081.rs b/src/test/run-pass/issue-30081.rs
new file mode 100644 (file)
index 0000000..13e9daa
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This used to segfault #30081
+
+pub enum Instruction {
+    Increment(i8),
+    Loop(Box<Box<()>>),
+}
+
+fn main() {
+    let instrs: Option<(u8, Box<Instruction>)> = None;
+    instrs.into_iter()
+        .map(|(_, instr)| instr)
+        .map(|instr| match *instr { _other => {} })
+        .last();
+}
index 5726f236e2e0b9f525d5a0de9c8d1a6a40b40007..21e3343f445869d81915c517deb06d3d72c084f8 100644 (file)
@@ -16,8 +16,7 @@ macro_rules! print_hd_tl {
             print!("{}", stringify!($field_tl));
             print!(", ");
         )+
-        // FIXME: #9970
-        print!("{}", "]\n");
+        print!("]\n");
     })
 }
 
diff --git a/src/test/run-pass/issue28498-must-work-ex1.rs b/src/test/run-pass/issue28498-must-work-ex1.rs
new file mode 100644 (file)
index 0000000..83a978d
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Example taken from RFC 1238 text
+
+// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
+//     #examples-of-code-that-must-continue-to-work
+
+use std::cell::Cell;
+
+struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>);
+
+fn main() {
+    let mut data = Vec::new();
+    data.push(Concrete(0, Cell::new(None)));
+    data.push(Concrete(0, Cell::new(None)));
+
+    data[0].1.set(Some(&data[1]));
+    data[1].1.set(Some(&data[0]));
+}
diff --git a/src/test/run-pass/issue28498-must-work-ex2.rs b/src/test/run-pass/issue28498-must-work-ex2.rs
new file mode 100644 (file)
index 0000000..93652a1
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Example taken from RFC 1238 text
+
+// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
+//     #examples-of-code-that-must-continue-to-work
+
+use std::cell::Cell;
+
+struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>);
+
+struct Foo<T> { data: Vec<T> }
+
+fn main() {
+    let mut foo = Foo {  data: Vec::new() };
+    foo.data.push(Concrete(0, Cell::new(None)));
+    foo.data.push(Concrete(0, Cell::new(None)));
+
+    foo.data[0].1.set(Some(&foo.data[1]));
+    foo.data[1].1.set(Some(&foo.data[0]));
+}
+
diff --git a/src/test/run-pass/issue28498-ugeh-ex1.rs b/src/test/run-pass/issue28498-ugeh-ex1.rs
new file mode 100644 (file)
index 0000000..b07831f
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Example taken from RFC 1238 text
+
+// https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
+//     #example-of-the-unguarded-escape-hatch
+
+#![feature(dropck_parametricity)]
+use std::cell::Cell;
+
+struct Concrete<'a>(u32, Cell<Option<&'a Concrete<'a>>>);
+
+struct Foo<T> { data: Vec<T> }
+
+impl<T> Drop for Foo<T> {
+    // Below is the UGEH attribute
+    #[unsafe_destructor_blind_to_params]
+    fn drop(&mut self) { }
+}
+
+fn main() {
+    let mut foo = Foo {  data: Vec::new() };
+    foo.data.push(Concrete(0, Cell::new(None)));
+    foo.data.push(Concrete(0, Cell::new(None)));
+
+    foo.data[0].1.set(Some(&foo.data[1]));
+    foo.data[1].1.set(Some(&foo.data[0]));
+}
+
diff --git a/src/test/run-pass/issue28498-ugeh-with-lifetime-param.rs b/src/test/run-pass/issue28498-ugeh-with-lifetime-param.rs
new file mode 100644 (file)
index 0000000..19be256
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Demonstrate the use of the unguarded escape hatch with a lifetime param
+// to assert that destructor will not access any dead data.
+//
+// Compare with compile-fail/issue28498-reject-lifetime-param.rs
+
+#![feature(dropck_parametricity)]
+
+#[derive(Debug)]
+struct ScribbleOnDrop(String);
+
+impl Drop for ScribbleOnDrop {
+    fn drop(&mut self) {
+        self.0 = format!("DROPPED");
+    }
+}
+
+struct Foo<'a>(u32, &'a ScribbleOnDrop);
+
+impl<'a> Drop for Foo<'a> {
+    #[unsafe_destructor_blind_to_params]
+    fn drop(&mut self) {
+        // Use of `unsafe_destructor_blind_to_params` is sound,
+        // because destructor never accesses `self.1`.
+        println!("Dropping Foo({}, _)", self.0);
+    }
+}
+
+fn main() {
+    let (last_dropped, foo0);
+    let (foo1, first_dropped);
+
+    last_dropped = ScribbleOnDrop(format!("last"));
+    first_dropped = ScribbleOnDrop(format!("first"));
+    foo0 = Foo(0, &last_dropped);
+    foo1 = Foo(1, &first_dropped);
+
+    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
+}
diff --git a/src/test/run-pass/issue28498-ugeh-with-passed-to-fn.rs b/src/test/run-pass/issue28498-ugeh-with-passed-to-fn.rs
new file mode 100644 (file)
index 0000000..bb430ea
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Demonstrate the use of the unguarded escape hatch with a type param in negative position
+// to assert that destructor will not access any dead data.
+//
+// Compare with compile-fail/issue28498-reject-lifetime-param.rs
+
+// Demonstrate that a type param in negative position causes dropck to reject code
+// that might indirectly access previously dropped value.
+//
+// Compare with run-pass/issue28498-ugeh-with-passed-to-fn.rs
+
+#![feature(dropck_parametricity)]
+
+#[derive(Debug)]
+struct ScribbleOnDrop(String);
+
+impl Drop for ScribbleOnDrop {
+    fn drop(&mut self) {
+        self.0 = format!("DROPPED");
+    }
+}
+
+struct Foo<T>(u32, T, Box<for <'r> fn(&'r T) -> String>);
+
+impl<T> Drop for Foo<T> {
+    #[unsafe_destructor_blind_to_params]
+    fn drop(&mut self) {
+        // Use of `unsafe_destructor_blind_to_params` is sound,
+        // because destructor never passes a `self.1` to the callback
+        // (in `self.2`) despite having it available.
+        println!("Dropping Foo({}, _)", self.0);
+    }
+}
+
+fn callback(s: & &ScribbleOnDrop) -> String { format!("{:?}", s) }
+
+fn main() {
+    let (last_dropped, foo0);
+    let (foo1, first_dropped);
+
+    last_dropped = ScribbleOnDrop(format!("last"));
+    first_dropped = ScribbleOnDrop(format!("first"));
+    foo0 = Foo(0, &last_dropped, Box::new(callback));
+    foo1 = Foo(1, &first_dropped, Box::new(callback));
+
+    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
+}
diff --git a/src/test/run-pass/issue28498-ugeh-with-trait-bound.rs b/src/test/run-pass/issue28498-ugeh-with-trait-bound.rs
new file mode 100644 (file)
index 0000000..2e9633b
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Demonstrate the use of the unguarded escape hatch with a trait bound
+// to assert that destructor will not access any dead data.
+//
+// Compare with compile-fail/issue28498-reject-trait-bound.rs
+
+#![feature(dropck_parametricity)]
+
+use std::fmt;
+
+#[derive(Debug)]
+struct ScribbleOnDrop(String);
+
+impl Drop for ScribbleOnDrop {
+    fn drop(&mut self) {
+        self.0 = format!("DROPPED");
+    }
+}
+
+struct Foo<T:fmt::Debug>(u32, T);
+
+impl<T:fmt::Debug> Drop for Foo<T> {
+    #[unsafe_destructor_blind_to_params]
+    fn drop(&mut self) {
+        // Use of `unsafe_destructor_blind_to_params` is sound,
+        // because destructor never accesses the `Debug::fmt` method
+        // of `T`, despite having it available.
+        println!("Dropping Foo({}, _)", self.0);
+    }
+}
+
+fn main() {
+    let (last_dropped, foo0);
+    let (foo1, first_dropped);
+
+    last_dropped = ScribbleOnDrop(format!("last"));
+    first_dropped = ScribbleOnDrop(format!("first"));
+    foo0 = Foo(0, &last_dropped);
+    foo1 = Foo(1, &first_dropped);
+
+    println!("foo0.1: {:?} foo1.1: {:?}", foo0.1, foo1.1);
+}
index e5bdca1a06773a8773eada2ece519870980db73d..ae5bf71d15fe4a59b293f88e5c1a79212235958b 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-test #9383
-
 // shouldn't affect evaluation of $ex:
 macro_rules! bad_macro {
     ($ex:expr) => ({(|_x| { $ex }) (9) })
index da57e8682ca602b0e11183da4f669081e1490dbe..34687c6ca1de31b40b56b9e5011d62ca476a7355 100644 (file)
@@ -31,10 +31,10 @@ struct Structure {
 }
 
 pub fn main() {
-    let x: Box<isize> = box(HEAP) 2;
+    let x: Box<isize> = in HEAP { 2 };
     let y: Box<isize> = box 2;
-    let b: Box<isize> = box()(1 + 2);
-    let c = box()(3 + 4);
+    let b: Box<isize> = box (1 + 2);
+    let c = box (3 + 4);
 
     let s: Box<Structure> = box Structure {
         x: 3,
diff --git a/src/test/run-pass/pushpop-unsafe-okay.rs b/src/test/run-pass/pushpop-unsafe-okay.rs
deleted file mode 100644 (file)
index fc402d4..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Basic sanity check for `push_unsafe!(EXPR)` and
-// `pop_unsafe!(EXPR)`: we can call unsafe code when there are a
-// positive number of pushes in the stack, or if we are within a
-// normal `unsafe` block, but otherwise cannot.
-
-// ignore-pretty because the `push_unsafe!` and `pop_unsafe!` macros
-// are not integrated with the pretty-printer.
-
-#![feature(pushpop_unsafe)]
-
-static mut X: i32 = 0;
-
-unsafe fn f() { X += 1; return; }
-fn g() { unsafe { X += 1_000; } return; }
-
-fn check_reset_x(x: i32) -> bool {
-    #![allow(unused_parens)] // dont you judge my style choices!
-    unsafe {
-        let ret = (x == X);
-        X = 0;
-        ret
-    }
-}
-
-fn main() {
-    // double-check test infrastructure
-    assert!(check_reset_x(0));
-    unsafe { f(); }
-    assert!(check_reset_x(1));
-    assert!(check_reset_x(0));
-    { g(); }
-    assert!(check_reset_x(1000));
-    assert!(check_reset_x(0));
-    unsafe { f(); g(); g(); }
-    assert!(check_reset_x(2001));
-
-    push_unsafe!( { f(); pop_unsafe!( g() ) } );
-    assert!(check_reset_x(1_001));
-    push_unsafe!( { g(); pop_unsafe!( unsafe { f(); f(); } ) } );
-    assert!(check_reset_x(1_002));
-
-    unsafe { push_unsafe!( { f(); pop_unsafe!( { f(); f(); } ) } ); }
-    assert!(check_reset_x(3));
-    push_unsafe!( { f(); push_unsafe!( { pop_unsafe!( { f(); f(); f(); } ) } ); } );
-    assert!(check_reset_x(4));
-}
index 72a214f4c9ad057eb5622997d630715c98c6330e..4ba04aa7091a8c93b2fd6c534a4d05eadd36ed12 100644 (file)
@@ -83,7 +83,7 @@ impl<'s> Trait<'s> for (isize,isize) {
 
 impl<'t> MakerTrait for Box<Trait<'t>+'static> {
     fn mk() -> Box<Trait<'t>+'static> {
-        let tup: Box<(isize, isize)> = box() (4,5);
+        let tup: Box<(isize, isize)> = box (4,5);
         tup as Box<Trait>
     }
 }
index a1c5ad113c76db0aa15ba13f4637e0da7b3231a6..d3d3de0e2c0cbc68b4f8f03dc2a258a10eb3da8d 100644 (file)
 
 
 extern crate sepcomp_cci_lib;
-use sepcomp_cci_lib::{cci_fn, CCI_STATIC};
+use sepcomp_cci_lib::{cci_fn, CCI_CONST};
 
 fn call1() -> usize {
-    cci_fn() + CCI_STATIC
+    cci_fn() + CCI_CONST
 }
 
 mod a {
-    use sepcomp_cci_lib::{cci_fn, CCI_STATIC};
+    use sepcomp_cci_lib::{cci_fn, CCI_CONST};
     pub fn call2() -> usize {
-        cci_fn() + CCI_STATIC
+        cci_fn() + CCI_CONST
     }
 }
 
 mod b {
-    use sepcomp_cci_lib::{cci_fn, CCI_STATIC};
+    use sepcomp_cci_lib::{cci_fn, CCI_CONST};
     pub fn call3() -> usize {
-        cci_fn() + CCI_STATIC
+        cci_fn() + CCI_CONST
     }
 }
 
index 4ff058f336661253f4a2f07380ec3cdd1a815d36..542e8de9e53ca8effb75cf5c841e4acf012596fc 100644 (file)
@@ -13,9 +13,6 @@
 // Check that we do *not* overflow on a number of edge cases.
 // (compare with test/run-fail/overflowing-{lsh,rsh}*.rs)
 
-// (Work around constant-evaluation)
-fn id<T>(x: T) -> T { x }
-
 fn main() {
     test_left_shift();
     test_right_shift();
@@ -26,34 +23,34 @@ fn test_left_shift() {
 
     macro_rules! tests {
         ($iN:ty, $uN:ty, $max_rhs:expr, $expect_i:expr, $expect_u:expr) => { {
-            let x = (1 as $iN) << id(0);
+            let x = (1 as $iN) << 0;
             assert_eq!(x, 1);
-            let x = (1 as $uN) << id(0);
+            let x = (1 as $uN) << 0;
             assert_eq!(x, 1);
-            let x = (1 as $iN) << id($max_rhs);
+            let x = (1 as $iN) << $max_rhs;
             assert_eq!(x, $expect_i);
-            let x = (1 as $uN) << id($max_rhs);
+            let x = (1 as $uN) << $max_rhs;
             assert_eq!(x, $expect_u);
             // high-order bits on LHS are silently discarded without panic.
-            let x = (3 as $iN) << id($max_rhs);
+            let x = (3 as $iN) << $max_rhs;
             assert_eq!(x, $expect_i);
-            let x = (3 as $uN) << id($max_rhs);
+            let x = (3 as $uN) << $max_rhs;
             assert_eq!(x, $expect_u);
         } }
     }
 
-    let x = 1_i8 << id(0);
+    let x = 1_i8 << 0;
     assert_eq!(x, 1);
-    let x = 1_u8 << id(0);
+    let x = 1_u8 << 0;
     assert_eq!(x, 1);
-    let x = 1_i8 << id(7);
+    let x = 1_i8 << 7;
     assert_eq!(x, std::i8::MIN);
-    let x = 1_u8 << id(7);
+    let x = 1_u8 << 7;
     assert_eq!(x, 0x80);
     // high-order bits on LHS are silently discarded without panic.
-    let x = 3_i8 << id(7);
+    let x = 3_i8 << 7;
     assert_eq!(x, std::i8::MIN);
-    let x = 3_u8 << id(7);
+    let x = 3_u8 << 7;
     assert_eq!(x, 0x80);
 
     // above is (approximately) expanded from:
@@ -71,23 +68,23 @@ fn test_right_shift() {
         ($iN:ty, $uN:ty, $max_rhs:expr,
          $signbit_i:expr, $highbit_i:expr, $highbit_u:expr) =>
         { {
-            let x = (1 as $iN) >> id(0);
+            let x = (1 as $iN) >> 0;
             assert_eq!(x, 1);
-            let x = (1 as $uN) >> id(0);
+            let x = (1 as $uN) >> 0;
             assert_eq!(x, 1);
-            let x = ($highbit_i) >> id($max_rhs-1);
+            let x = ($highbit_i) >> $max_rhs-1;
             assert_eq!(x, 1);
-            let x = ($highbit_u) >> id($max_rhs);
+            let x = ($highbit_u) >> $max_rhs;
             assert_eq!(x, 1);
             // sign-bit is carried by arithmetic right shift
-            let x = ($signbit_i) >> id($max_rhs);
+            let x = ($signbit_i) >> $max_rhs;
             assert_eq!(x, -1);
             // low-order bits on LHS are silently discarded without panic.
-            let x = ($highbit_i + 1) >> id($max_rhs-1);
+            let x = ($highbit_i + 1) >> $max_rhs-1;
             assert_eq!(x, 1);
-            let x = ($highbit_u + 1) >> id($max_rhs);
+            let x = ($highbit_u + 1) >> $max_rhs;
             assert_eq!(x, 1);
-            let x = ($signbit_i + 1) >> id($max_rhs);
+            let x = ($signbit_i + 1) >> $max_rhs;
             assert_eq!(x, -1);
         } }
     }
index 8160fe56fd0b27adfcdda9407b2996c15d095705..7fa592105c09d4900d14236fe028016c86cf9329 100644 (file)
@@ -93,7 +93,8 @@ fn main() {
     }
     all_sync_send!(EnumSet::<Foo>::new(), iter);
 
-    all_sync_send!(VecDeque::<usize>::new(), iter, iter_mut, drain, into_iter);
+    all_sync_send!(VecDeque::<usize>::new(), iter, iter_mut, into_iter);
+    is_sync_send!(VecDeque::<usize>::new(), drain(..));
 
     all_sync_send!(Vec::<usize>::new(), into_iter);
     is_sync_send!(Vec::<usize>::new(), drain(..));
index 15a8a2e83e340572f1d25f1a26447f1731da89cf..33bee3ea06f4dbab6fe53414abe0b2d76ba42d17 100644 (file)
@@ -49,6 +49,6 @@ impl<V> Trait<u8,V> for () {
 }
 
 pub fn main() {
-    let a = box() () as Box<Trait<u8, u8>>;
+    let a = box () as Box<Trait<u8, u8>>;
     assert_eq!(a.method(Type::Constant((1, 2))), 0);
 }
index 9d685e0263f22c007988fb52cda9d2f8e9e6a0e9..fdb70fe248eff1bc456ebbf60557582488d985b0 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(negate_unsigned)]
+
 pub fn main() {
     let a = 1;
     let a_neg: i8 = -a;
index 65522bd95df7fc0af6d2faa0eed458285bbe06e3..d5da8b35b6db40af7c11479de5d6859784384aea 100644 (file)
@@ -10,7 +10,7 @@
 
 use std::cell::Cell;
 
-#[derive(Show)]
+#[derive(Debug)]
 struct C<'a> {
     v: Vec<Cell<Option<&'a C<'a>>>>,
 }
index f179df90b34cabce9deee49e5446a9ec4c9cefaa..56480268a01b2adff5aa9766c4021163937910ed 100644 (file)
 
 use std::cell::Cell;
 
-#[derive(Show)]
+#[derive(Debug)]
 struct Refs<'a> {
     v: Vec<Cell<Option<&'a C<'a>>>>,
 }
 
-#[derive(Show)]
+#[derive(Debug)]
 struct C<'a> {
     refs: Refs<'a>,
 }
index 48eea1206230ec5349a3254655de3a705034ec29..5470ad93e142644c217a0404422d1466f78c5308 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(num_wrapping)]
-
 // Test inherent wrapping_* methods for {i,u}{size,8,16,32,64}.
 
 use std::{i8, i16, i32, i64, isize};
index c9742b0645e1da9e3a65479df800f32004cacdb6..f3bf5d9c6843fca5b00d4558959770ff67c61a86 100644 (file)
@@ -10,7 +10,7 @@
 
 #![feature(std_misc)]
 
-pub type HANDLE = u32;
+pub type HANDLE = usize;
 pub type DWORD = u32;
 pub type SIZE_T = u32;
 pub type LPVOID = usize;
index af67f7e2c1fb7bd2a2d412f7581eb1ba0f864a4e..e05d51c2bac58464a26601b5b2852fc2f95b0078 100644 (file)
@@ -12,8 +12,6 @@
 /// retained.
 ///
 /// ```rust
-/// mod to_make_deriving_work { // FIXME #4913
-///
 /// # #[derive(PartialEq)] // invisible
 /// # struct Foo; // invisible
 ///
@@ -24,8 +22,6 @@
 ///     let x = Bar(Foo);
 ///     assert_eq!(x, x); // check that the derivings worked
 /// }
-///
-/// }
 /// ```
 pub fn foo() {}